input-group
Use .input-group with one native control and optional authored addons, text,
and buttons. AngularTS continues to own the model and actions.
<div class="input-group">
<input id="search" placeholder="Search" />
<label for="search" align="inline-start">Search</label>
<div align="inline-end">⌘K</div>
</div>
Example
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body ng-app="angular.css" ng-cloak>
<main class="stack">
<div class="field">
<label for="search">Search</label>
<div class="input-group">
<input id="search" placeholder="Search documentation..." />
<label for="search" align="inline-start">
<span aria-hidden="true">⌕</span>
</label>
</div>
</div>
</main>
</body>
</html>
Reference Workflows
These packaged examples cover default, disabled, invalid, inline, text, icon, keyboard-hint, label, Button Group, and Card compositions.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group Workflows</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="query=''; message=''; copyStatus='Ready'; cardStatus=''; username='angularcss'"
data-example="input-group-workflows"
>
<svg class="example-icon-definitions" aria-hidden="true">
<defs>
<symbol id="ig-search" viewBox="0 0 24 24">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.3-4.3"></path>
</symbol>
<symbol id="ig-mail" viewBox="0 0 24 24">
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
<path d="m22 7-10 6L2 7"></path>
</symbol>
<symbol id="ig-card" viewBox="0 0 24 24">
<rect width="20" height="14" x="2" y="5" rx="2"></rect>
<path d="M2 10h20"></path>
</symbol>
<symbol id="ig-check" viewBox="0 0 24 24">
<path d="m5 12 4 4L19 6"></path>
</symbol>
<symbol id="ig-eye-off" viewBox="0 0 24 24">
<path d="m2 2 20 20"></path>
<path
d="M6.7 6.7C4.8 8 3.3 9.8 2.5 12c1.5 4 5.2 7 9.5 7 1.5 0 2.9-.3 4.1-.9"
></path>
<path
d="M10.7 5.1A10 10 0 0 1 12 5c4.3 0 8 3 9.5 7a10.8 10.8 0 0 1-2.1 3.4"
></path>
</symbol>
<symbol id="ig-star" viewBox="0 0 24 24">
<path
d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2L5.8 21 7 14.2 2 9.3l6.9-1Z"
></path>
</symbol>
<symbol id="ig-info" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4M12 8h.01"></path>
</symbol>
<symbol id="ig-link" viewBox="0 0 24 24">
<path
d="M10 13a5 5 0 0 0 7.1.1l2-2a5 5 0 0 0-7.1-7.1l-1.1 1.1"
></path>
<path d="M14 11a5 5 0 0 0-7.1-.1l-2 2A5 5 0 0 0 12 20l1.1-1.1"></path>
</symbol>
</defs>
</svg>
<main class="input-group-workflow-grid" aria-label="Input group examples">
<section
class="input-group-workflow"
data-example="input-group-basic"
aria-labelledby="input-group-basic-title"
>
<h2 id="input-group-basic-title">States</h2>
<div class="field-group">
<div class="field">
<label for="ig-default">Default</label>
<input id="ig-default" placeholder="Placeholder" />
</div>
<div class="field">
<label for="ig-basic">Input group</label>
<div class="input-group">
<input id="ig-basic" placeholder="Placeholder" />
</div>
</div>
<div class="field">
<label for="ig-disabled">Disabled</label>
<div class="input-group">
<input
id="ig-disabled"
placeholder="This field is disabled"
disabled
/>
</div>
</div>
<div class="field">
<label for="ig-invalid">Invalid</label>
<div class="input-group">
<input
id="ig-invalid"
placeholder="This field is invalid"
aria-invalid="true"
/>
</div>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-demo input-group-inline-start input-group-inline-end input-group-kbd"
aria-labelledby="input-group-position-title"
>
<h2 id="input-group-position-title">Inline addons</h2>
<div class="input-group">
<input
ng-model="query"
placeholder="Search..."
aria-label="Search documentation"
/>
<div align="inline-start">
<svg aria-hidden="true"><use href="#ig-search"></use></svg>
</div>
<div align="inline-end">{{ query ? '12 results' : 'No query' }}</div>
</div>
<div class="input-group">
<input
type="password"
placeholder="Enter password"
aria-label="Password"
/>
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-eye-off"></use></svg>
</div>
</div>
<div class="input-group">
<input id="ig-command-search" placeholder="Search commands..." />
<label for="ig-command-search">
<svg aria-hidden="true"><use href="#ig-search"></use></svg>
</label>
<div align="inline-end">
<kbd>⌘K</kbd>
</div>
</div>
<output class="input-group-output">
Query: {{ query || 'none' }}
</output>
</section>
<section
class="input-group-workflow"
data-example="input-group-icon"
aria-labelledby="input-group-icon-title"
>
<h2 id="input-group-icon-title">Icons</h2>
<div class="input-group">
<input
type="email"
placeholder="Enter your email"
aria-label="Email with icon"
/>
<div>
<svg aria-hidden="true"><use href="#ig-mail"></use></svg>
</div>
</div>
<div class="input-group">
<input placeholder="Card number" aria-label="Verified card number" />
<div>
<svg aria-hidden="true"><use href="#ig-card"></use></svg>
</div>
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-check"></use></svg>
</div>
</div>
<div class="input-group">
<input placeholder="Favorite card" aria-label="Favorite card" />
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-star"></use></svg>
<svg aria-hidden="true"><use href="#ig-info"></use></svg>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-text"
aria-labelledby="input-group-text-title"
>
<h2 id="input-group-text-title">Text addons</h2>
<div class="input-group">
<div>
<span>$</span>
</div>
<input inputmode="decimal" placeholder="0.00" aria-label="Amount" />
<div align="inline-end">
<span>USD</span>
</div>
</div>
<div class="input-group">
<div>
<span>https://</span>
</div>
<input placeholder="example.com" aria-label="Website" />
<div align="inline-end">
<span>.com</span>
</div>
</div>
<div class="input-group">
<input
placeholder="Enter your username"
aria-label="Company username"
/>
<div align="inline-end">
<span>@company.com</span>
</div>
</div>
</section>
<section
class="input-group-workflow input-group-workflow-wide"
data-example="input-group-with-addons"
aria-labelledby="input-group-addons-title"
>
<h2 id="input-group-addons-title">Addon positions</h2>
<div class="input-group-pair-grid">
<div class="field">
<label for="ig-addon-start">Inline start and end</label>
<div class="input-group">
<input id="ig-addon-start" />
<div>
<svg aria-hidden="true"><use href="#ig-search"></use></svg>
</div>
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-info"></use></svg>
</div>
</div>
</div>
<div class="field">
<label for="ig-addon-header">Block start</label>
<div class="input-group">
<input id="ig-addon-header" />
<div align="block-start">
<span>First name</span>
<svg class="input-group-push-end" aria-hidden="true">
<use href="#ig-info"></use>
</svg>
</div>
</div>
</div>
<div class="field">
<label for="ig-addon-footer">Block end</label>
<div class="input-group">
<input id="ig-addon-footer" />
<div align="block-end">
<span>20/240 characters</span>
<svg class="input-group-push-end" aria-hidden="true">
<use href="#ig-info"></use>
</svg>
</div>
</div>
</div>
<div class="field">
<label for="ig-addon-optional">Label and optional text</label>
<div class="input-group">
<div>
<label for="ig-addon-optional">Label</label>
</div>
<input id="ig-addon-optional" />
<div align="inline-end">
<span>(optional)</span>
</div>
</div>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-with-kbd"
aria-labelledby="input-group-kbd-title"
>
<h2 id="input-group-kbd-title">Keyboard hints</h2>
<div class="input-group">
<input placeholder="Search for apps..." aria-label="Search apps" />
<div align="inline-end">Ask AI</div>
<div align="inline-end">
<kbd>Tab</kbd>
</div>
</div>
<div class="input-group">
<input ng-model="username" aria-label="Username" />
<div align="inline-end">
<span class="input-group-valid-icon"
><svg aria-hidden="true"><use href="#ig-check"></use></svg
></span>
</div>
</div>
<p class="input-group-success">This username is available.</p>
<div class="input-group">
<input value="angularcss" aria-label="Loading username" disabled />
<div align="inline-end">
<output size="sm" aria-label="Loading" class="spinner"></output>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-label"
aria-labelledby="input-group-label-title"
>
<h2 id="input-group-label-title">Labels in addons</h2>
<div class="input-group">
<input id="ig-email-name" placeholder="angularcss" />
<div>
<label for="ig-email-name">@</label>
</div>
</div>
<div class="input-group">
<input id="ig-email-address" placeholder="team@angularcss.dev" />
<div align="block-start">
<label for="ig-email-address">Email</label>
<span ng-tooltip class="input-group-push-end">
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Email help"
>
<svg aria-hidden="true"><use href="#ig-info"></use></svg>
</button>
<span side="top">We'll use this to send notifications.</span>
</span>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-button-group"
aria-labelledby="input-group-button-group-title"
>
<h2 id="input-group-button-group-title">Button group</h2>
<div role="group">
<label for="ig-url">https://</label>
<div class="input-group">
<input id="ig-url" aria-label="URL" />
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-link"></use></svg>
</div>
</div>
<span>.com</span>
</div>
</section>
<section
class="input-group-workflow input-group-card-workflow"
data-example="input-group-in-card"
aria-labelledby="input-group-card-title"
>
<article class="card">
<header>
<h2 id="input-group-card-title">Card with input group</h2>
<p>Collect contact details and feedback.</p>
</header>
<section>
<div class="field-group">
<div class="field">
<label for="ig-card-email">Email address</label>
<div class="input-group">
<input
id="ig-card-email"
type="email"
placeholder="you@example.com"
/>
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-mail"></use></svg>
</div>
</div>
</div>
<div class="field">
<label for="ig-card-site">Website URL</label>
<div class="input-group">
<div>
<span>https://</span>
</div>
<input id="ig-card-site" placeholder="example.com" />
<div align="inline-end">
<svg aria-hidden="true"><use href="#ig-link"></use></svg>
</div>
</div>
</div>
</div>
</section>
<footer class="input-group-card-actions">
<button
variant="outline"
type="button"
ng-click="cardStatus='Cancelled'"
>
Cancel
</button>
<button type="button" ng-click="cardStatus='Submitted'">
Submit
</button>
<output class="input-group-output">{{ cardStatus }}</output>
</footer>
</article>
</section>
</main>
</body>
</html>
Interactive Compositions
Buttons, dropdown menus, tooltips, popovers, calling-code selection, and mixed Button Group compositions run from AngularTS bindings in the built artifact.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group Compositions</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="copied=false; favorite=false; country='+1'; compositionStatus='Ready'"
data-example="input-group-compositions"
>
<svg class="example-icon-definitions" aria-hidden="true">
<defs>
<symbol id="igc-copy" viewBox="0 0 24 24">
<rect width="14" height="14" x="8" y="8" rx="2"></rect>
<path
d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
></path>
</symbol>
<symbol id="igc-check" viewBox="0 0 24 24">
<path d="m5 12 4 4L19 6"></path>
</symbol>
<symbol id="igc-star" viewBox="0 0 24 24">
<path
d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2L5.8 21 7 14.2 2 9.3l6.9-1Z"
></path>
</symbol>
<symbol id="igc-info" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4M12 8h.01"></path>
</symbol>
<symbol id="igc-help" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10"></circle>
<path d="M9.1 9a3 3 0 1 1 5.8 1c0 2-3 2-3 4M12 18h.01"></path>
</symbol>
<symbol id="igc-more" viewBox="0 0 24 24">
<circle cx="5" cy="12" r="1"></circle>
<circle cx="12" cy="12" r="1"></circle>
<circle cx="19" cy="12" r="1"></circle>
</symbol>
<symbol id="igc-chevron" viewBox="0 0 24 24">
<path d="m6 9 6 6 6-6"></path>
</symbol>
<symbol id="igc-trash" viewBox="0 0 24 24">
<path d="M3 6h18M8 6V4h8v2M19 6l-1 16H6L5 6M10 11v6M14 11v6"></path>
</symbol>
</defs>
</svg>
<main
class="input-group-composition-grid"
aria-label="Interactive input group compositions"
>
<section
class="input-group-workflow"
data-example="input-group-button"
aria-labelledby="igc-button-title"
>
<h2 id="igc-button-title">Buttons</h2>
<div class="input-group">
<input
value="https://x.com/angularcss"
aria-label="Share URL"
readonly
/>
<div align="inline-end">
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Copy URL"
ng-click="copied=true; compositionStatus='Copied URL'"
>
<svg aria-hidden="true">
<use ng-if="!copied" href="#igc-copy"></use>
<use ng-if="copied" href="#igc-check"></use>
</svg>
</button>
</div>
</div>
<div class="input-group-pill input-group">
<span>
<button
size="icon-xs"
variant="secondary"
type="button"
aria-label="Connection information"
popovertarget="popover-input-group-compositions-1-content"
>
<svg aria-hidden="true"><use href="#igc-info"></use></svg>
</button>
<aside
class="input-group-popover-content"
aria-label="Connection status"
id="popover-input-group-compositions-1-content"
side="bottom"
align="start"
popover
>
<strong>Your connection is not secure.</strong>
<p>You should not enter sensitive information on this site.</p>
</aside>
</span>
<div>https://</div>
<input aria-label="Secure URL" />
<div align="inline-end">
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Favorite URL"
aria-pressed="{{ favorite }}"
ng-click="favorite=!favorite; compositionStatus=favorite ? 'Added favorite' : 'Removed favorite'"
>
<svg aria-hidden="true">
<use href="#igc-star"></use>
</svg>
</button>
</div>
</div>
<div class="input-group">
<input placeholder="Type to search..." aria-label="Search query" />
<div align="inline-end">
<button
variant="secondary"
type="button"
ng-click="compositionStatus='Search submitted'"
>
Search
</button>
</div>
</div>
<output class="input-group-output">{{ compositionStatus }}</output>
</section>
<section
class="input-group-workflow"
data-example="input-group-with-buttons"
aria-labelledby="igc-variants-title"
>
<h2 id="igc-variants-title">Button variants</h2>
<div class="input-group">
<input aria-label="Default action" />
<div>
<button type="button" ng-click="compositionStatus='Default action'">
Default
</button>
</div>
</div>
<div class="input-group">
<input aria-label="Outline action" />
<div>
<button
variant="outline"
type="button"
ng-click="compositionStatus='Outline action'"
>
Outline
</button>
</div>
</div>
<div class="input-group">
<input aria-label="Secondary action" />
<div align="inline-end">
<button
variant="secondary"
type="button"
ng-click="compositionStatus='Secondary action'"
>
Button
</button>
</div>
</div>
<div class="input-group">
<input aria-label="Delete action" />
<div align="inline-end">
<button
size="icon-xs"
variant="secondary"
type="button"
aria-label="Delete"
ng-click="compositionStatus='Deleted'"
>
<svg aria-hidden="true"><use href="#igc-trash"></use></svg>
</button>
</div>
</div>
</section>
<section
class="input-group-workflow input-group-menu-workflow"
data-example="input-group-dropdown"
aria-labelledby="igc-dropdown-title"
>
<h2 id="igc-dropdown-title">Dropdown menus</h2>
<div class="input-group">
<input placeholder="Enter file name" aria-label="File name" />
<div align="inline-end">
<span ng-dropdown-menu class="input-group-overlay-control">
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="File options"
>
<svg aria-hidden="true"><use href="#igc-more"></use></svg>
</button>
<menu align="end" style="--menu-width: 10rem">
<button ng-click="compositionStatus='Settings'">
Settings
</button>
<button ng-click="compositionStatus='Copied path'">
Copy path
</button>
<button ng-click="compositionStatus='Opened location'">
Open location
</button>
</menu>
</span>
</div>
</div>
<div class="input-group">
<input
placeholder="Enter search query"
aria-label="Search query with scope"
/>
<div align="inline-end">
<span ng-dropdown-menu class="input-group-overlay-control">
<button variant="ghost" type="button">
Search in
<svg aria-hidden="true"><use href="#igc-chevron"></use></svg>
</button>
<menu align="end" style="--menu-width: 10rem">
<button ng-click="compositionStatus='Documentation'">
Documentation
</button>
<button ng-click="compositionStatus='Blog posts'">
Blog posts
</button>
<button ng-click="compositionStatus='Changelog'">
Changelog
</button>
</menu>
</span>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-tooltip"
aria-labelledby="igc-tooltip-title"
>
<h2 id="igc-tooltip-title">Tooltips</h2>
<div class="input-group">
<input
type="password"
placeholder="Enter password"
aria-label="Password requirements"
/>
<div align="inline-end">
<span ng-tooltip>
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Password information"
>
<svg aria-hidden="true"><use href="#igc-info"></use></svg>
</button>
<span side="top">Password must be at least 8 characters.</span>
</span>
</div>
</div>
<div class="input-group">
<input
placeholder="Your email address"
aria-label="Notification email"
/>
<div align="inline-end">
<span ng-tooltip>
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Email help"
>
<svg aria-hidden="true"><use href="#igc-help"></use></svg>
</button>
<span side="top">We'll use this to send notifications.</span>
</span>
</div>
</div>
<div class="input-group">
<input placeholder="Enter API key" aria-label="API key" />
<div align="inline-end">
<span ng-tooltip>
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="API key help"
>
<svg aria-hidden="true"><use href="#igc-help"></use></svg>
</button>
<span side="left">Click for help with API keys.</span>
</span>
</div>
</div>
</section>
<section
class="input-group-workflow input-group-workflow-wide"
data-example="input-group-with-tooltip"
aria-labelledby="igc-mixed-title"
>
<h2 id="igc-mixed-title">Mixed interactive controls</h2>
<div class="input-group-pair-grid">
<div class="field">
<label for="igc-tooltip-input">Tooltip</label>
<div class="input-group">
<input id="igc-tooltip-input" />
<div align="inline-end">
<span ng-tooltip
><button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Input information"
>
<svg aria-hidden="true">
<use href="#igc-info"></use>
</svg></button
><span side="top">This is content in a tooltip.</span></span
>
</div>
</div>
<p>This is a description of the input group.</p>
</div>
<div class="field">
<label for="igc-country-input">Dropdown</label>
<div class="input-group">
<input id="igc-country-input" type="tel" />
<div>
<span ng-dropdown-menu class="input-group-overlay-control">
<button variant="ghost" type="button">
{{ country }}
<svg aria-hidden="true">
<use href="#igc-chevron"></use>
</svg>
</button>
<menu align="end" style="--menu-width: 5rem">
<button ng-click="country='+1'">+1</button>
<button ng-click="country='+44'">+44</button>
<button ng-click="country='+46'">+46</button>
</menu>
</span>
</div>
</div>
<p>Select a calling code.</p>
</div>
<div class="field">
<label for="igc-popover-input">Popover</label>
<div class="input-group">
<span>
<button
size="icon-xs"
variant="secondary"
type="button"
aria-label="Security details"
popovertarget="popover-input-group-compositions-2-content"
>
<svg aria-hidden="true"><use href="#igc-info"></use></svg>
</button>
<aside
class="input-group-popover-content"
aria-label="Security details"
id="popover-input-group-compositions-2-content"
side="bottom"
align="start"
popover
>
<strong>Your connection is not secure.</strong>
<p>Do not enter sensitive information on this site.</p>
</aside>
</span>
<div>https://</div>
<input id="igc-popover-input" />
<div align="inline-end">
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Add favorite"
ng-click="compositionStatus='Added to favorites'"
>
<svg aria-hidden="true"><use href="#igc-star"></use></svg>
</button>
</div>
</div>
</div>
<div class="field">
<label for="igc-group-url">Button group</label>
<div role="group">
<span>https://</span>
<div class="input-group">
<input id="igc-group-url" />
<div align="inline-end">
<svg aria-hidden="true"><use href="#igc-info"></use></svg>
</div>
</div>
<span>.com</span>
</div>
</div>
</div>
</section>
</main>
</body>
</html>
Textarea And Block Addons
Block-start and block-end addons, textarea states, a code editor, character counters, and the autosizing custom control remain native form controls.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group Textarea Workflows</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="comment=''; commentCount=0; code=''; codeColumn=1; customText=''; customCount=0; textareaStatus='Ready'"
data-example="input-group-textarea-workflows"
>
<svg class="example-icon-definitions" aria-hidden="true">
<defs>
<symbol id="igt-copy" viewBox="0 0 24 24">
<rect width="14" height="14" x="8" y="8" rx="2"></rect>
<path
d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
></path>
</symbol>
<symbol id="igt-refresh" viewBox="0 0 24 24">
<path d="M20 11a8 8 0 1 0 2 5M20 4v7h-7"></path>
</symbol>
<symbol id="igt-code-icon" viewBox="0 0 24 24">
<path d="m16 18 6-6-6-6M8 6l-6 6 6 6M14.5 4l-5 16"></path>
</symbol>
<symbol id="igt-send" viewBox="0 0 24 24">
<path d="m22 2-7 20-4-9-9-4ZM22 2 11 13"></path>
</symbol>
<symbol id="igt-info" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4M12 8h.01"></path>
</symbol>
</defs>
</svg>
<main
class="input-group-textarea-grid"
aria-label="Input group textarea examples"
>
<section
class="input-group-workflow"
data-example="input-group-block-start"
aria-labelledby="igt-start-title"
>
<h2 id="igt-start-title">Block start</h2>
<div class="field">
<label for="igt-start-input">Input</label>
<div class="input-group">
<input id="igt-start-input" placeholder="Enter your name" />
<div align="block-start">
<span>Full name</span>
</div>
</div>
<p>Header positioned above the input.</p>
</div>
<div class="field">
<label for="igt-start-textarea">Textarea</label>
<div class="input-group">
<textarea
id="igt-start-textarea"
placeholder="console.log('Hello, world!');"
></textarea>
<div align="block-start" border="true">
<svg aria-hidden="true"><use href="#igt-code-icon"></use></svg>
<span class="input-group-mono">script.js</span>
<button
size="icon-xs"
class="input-group-push-end"
variant="ghost"
type="button"
aria-label="Copy code"
ng-click="textareaStatus='Copied code'"
>
<svg aria-hidden="true"><use href="#igt-copy"></use></svg>
</button>
</div>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-block-end"
aria-labelledby="igt-end-title"
>
<h2 id="igt-end-title">Block end</h2>
<div class="field">
<label for="igt-amount">Input</label>
<div class="input-group">
<input
id="igt-amount"
inputmode="decimal"
placeholder="Enter amount"
/>
<div align="block-end">
<span>USD</span>
</div>
</div>
<p>Footer positioned below the input.</p>
</div>
<div class="field">
<label for="igt-comment">Textarea</label>
<div class="input-group">
<textarea
id="igt-comment"
ng-model="comment"
data-change="commentCount=comment.length"
maxlength="280"
placeholder="Write a comment..."
></textarea>
<div align="block-end">
<span>{{ commentCount }}/280</span>
<button
size="sm"
class="input-group-push-end"
type="button"
ng-click="textareaStatus='Posted comment'"
>
Post
</button>
</div>
</div>
<p>Footer positioned below the textarea.</p>
</div>
</section>
<section
class="input-group-workflow input-group-workflow-wide"
data-example="input-group-textarea"
aria-labelledby="igt-editor-title"
>
<h2 id="igt-editor-title">Code editor</h2>
<div class="input-group-code-editor input-group">
<textarea
id="igt-code"
ng-model="code"
data-change="codeColumn=code.length+1"
placeholder="console.log('Hello, world!');"
aria-label="JavaScript code"
></textarea>
<div align="block-start" border="true">
<span class="input-group-mono"
><svg aria-hidden="true"><use href="#igt-code-icon"></use></svg
>script.js</span
>
<button
size="icon-xs"
class="input-group-push-end"
variant="ghost"
type="button"
aria-label="Refresh code"
ng-click="code=''; textareaStatus='Reset code'"
>
<svg aria-hidden="true"><use href="#igt-refresh"></use></svg>
</button>
<button
size="icon-xs"
variant="ghost"
type="button"
aria-label="Copy code"
ng-click="textareaStatus='Copied code'"
>
<svg aria-hidden="true"><use href="#igt-copy"></use></svg>
</button>
</div>
<div align="block-end" border="true">
<span>Line 1, Column {{ codeColumn }}</span>
<button
size="sm"
class="input-group-push-end"
type="button"
ng-click="textareaStatus='Ran code'"
>
Run
</button>
</div>
</div>
<output class="input-group-output">{{ textareaStatus }}</output>
</section>
<section
class="input-group-workflow input-group-workflow-wide"
data-example="input-group-textarea-examples"
aria-labelledby="igt-examples-title"
>
<h2 id="igt-examples-title">Textarea states and addons</h2>
<div class="input-group-pair-grid">
<div class="field">
<label for="igt-default-textarea">Default textarea</label>
<textarea
id="igt-default-textarea"
placeholder="Enter your text here..."
></textarea>
</div>
<div class="field">
<label for="igt-invalid-textarea">Invalid</label>
<div class="input-group">
<textarea
id="igt-invalid-textarea"
aria-invalid="true"
placeholder="Enter your text here..."
></textarea>
</div>
</div>
<div class="field">
<label for="igt-disabled-textarea">Disabled</label>
<div class="input-group">
<textarea
id="igt-disabled-textarea"
disabled
placeholder="Enter your text here..."
></textarea>
</div>
</div>
<div class="field">
<label for="igt-prompt">Addon (block start)</label>
<div class="input-group">
<textarea id="igt-prompt"></textarea>
<div align="block-start">
<span>Ask, search or chat...</span
><svg class="input-group-push-end" aria-hidden="true">
<use href="#igt-info"></use>
</svg>
</div>
</div>
</div>
<div class="field">
<label for="igt-send-comment">Addon (send)</label>
<div class="input-group">
<textarea
id="igt-send-comment"
ng-model="comment"
data-change="commentCount=comment.length"
placeholder="Enter your text here..."
></textarea>
<div align="block-end">
<span>{{ commentCount }}/280 characters</span
><button
size="icon-xs"
class="input-group-push-end input-group-round-button"
type="button"
aria-label="Send"
ng-click="textareaStatus='Sent message'"
>
<svg aria-hidden="true"><use href="#igt-send"></use></svg>
</button>
</div>
</div>
</div>
<div class="field">
<label for="igt-actions">Addon (buttons)</label>
<div class="input-group">
<textarea
id="igt-actions"
placeholder="Share your thoughts..."
></textarea>
<div align="block-end">
<button
size="sm"
class="input-group-push-end"
variant="ghost"
type="button"
ng-click="textareaStatus='Cancelled comment'"
>
Cancel</button
><button
size="sm"
type="button"
ng-click="textareaStatus='Posted comment'"
>
Post comment
</button>
</div>
</div>
</div>
</div>
</section>
<section
class="input-group-workflow"
data-example="input-group-custom"
aria-labelledby="igt-custom-title"
>
<h2 id="igt-custom-title">Autosizing custom control</h2>
<div class="input-group">
<textarea
class="input-group-autosize"
ng-model="customText"
data-change="customCount=customText.length"
placeholder="Autoresize textarea..."
aria-label="Autosize textarea"
></textarea>
<div align="block-end">
<span>{{ customCount }} characters</span
><button
size="sm"
class="input-group-push-end"
type="button"
ng-click="textareaStatus='Submitted custom text'"
>
Submit
</button>
</div>
</div>
</section>
</main>
</body>
</html>
Right To Left
Logical addon placement and AngularTS model updates work without RTL-specific component markup.
View source
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group Rtl</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="rtlQuery=''; rtlComment=''; rtlCount=0; rtlStatus='جاهز'"
data-example="input-group-rtl"
>
<main
class="input-group-rtl-workflow"
aria-label="مجموعات إدخال من اليمين إلى اليسار"
>
<div class="input-group">
<input ng-model="rtlQuery" placeholder="بحث..." aria-label="بحث" />
<div align="inline-start">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.3-4.3"></path>
</svg>
</div>
<div align="inline-end">١٢ نتيجة</div>
</div>
<div class="input-group">
<input placeholder="جاري البحث..." aria-label="جاري البحث" />
<div align="inline-end">
<output size="sm" aria-label="تحميل" class="spinner"></output>
</div>
</div>
<div class="input-group">
<input placeholder="جاري حفظ التغييرات..." aria-label="جاري الحفظ" />
<div align="inline-end">
<span>جاري الحفظ...</span
><output size="sm" aria-label="تحميل" class="spinner"></output>
</div>
</div>
<div class="field">
<label for="input-group-rtl-comment">منطقة النص</label>
<div class="input-group">
<textarea
id="input-group-rtl-comment"
ng-model="rtlComment"
data-change="rtlCount=rtlComment.length"
maxlength="280"
placeholder="اكتب تعليقًا..."
></textarea>
<div align="block-end">
<span>{{ rtlCount }}/٢٨٠</span>
<button
size="sm"
class="input-group-push-end"
type="button"
ng-click="rtlStatus='تم النشر'"
>
نشر
</button>
</div>
</div>
<p>تذييل موضع أسفل منطقة النص.</p>
</div>
<output class="input-group-output">
{{ rtlStatus }} · {{ rtlQuery || 'لا يوجد بحث' }}
</output>
</main>
</body>
</html>
Addon States
Visible addons participate in the control description. AngularCSS preserves external description IDs as AngularTS inserts or hides addon content.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Input Group State Workflows</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="query='AngularCSS'; showCurrency=false; priceHidden=false"
>
<main class="component-state-grid" aria-label="Input group state contracts">
<section
class="component-state-section"
aria-labelledby="described-group-title"
>
<h2 id="described-group-title">Described addons</h2>
<p id="external-help" class="component-state-help">
Enter an invoice total.
</p>
<div id="described-group" class="input-group">
<input
aria-label="Invoice total"
aria-describedby="external-help currency-code"
/>
<span id="currency-code">USD</span>
<span align="inline-end" aria-hidden="true"> .00 </span>
</div>
</section>
<section
class="component-state-section"
aria-labelledby="button-group-title"
>
<h2 id="button-group-title">Action button</h2>
<div id="button-group" class="input-group">
<input aria-label="Documentation search" ng-model="query" />
<button type="button" ng-click="query=''">Clear</button>
</div>
</section>
<section
class="component-state-section"
aria-labelledby="dynamic-group-title"
>
<h2 id="dynamic-group-title">Conditional addon</h2>
<div id="dynamic-group" class="input-group">
<input
ng-attr-aria-label="{{ showCurrency ? 'Budget in USD' : 'Budget' }}"
aria-describedby="budget-help"
/>
<span ng-if="showCurrency" id="dynamic-addon"> USD </span>
</div>
<p id="budget-help" class="component-state-help">Monthly budget</p>
<button
variant="outline"
type="button"
ng-click="showCurrency=true"
ng-disabled="showCurrency"
>
Add currency
</button>
</section>
<section
class="component-state-section"
aria-labelledby="hidden-group-title"
>
<h2 id="hidden-group-title">Hidden addon</h2>
<div id="hidden-group" class="input-group">
<input aria-label="Price" aria-describedby="price-help" />
<span id="addon-price" ng-attr-aria-hidden="{{ priceHidden }}">
USD
</span>
</div>
<p id="price-help" class="component-state-help">Price before tax</p>
<button
variant="outline"
type="button"
ng-click="priceHidden=!priceHidden"
>
Toggle currency description
</button>
</section>
</main>
</body>
</html>
Clicking a non-button addon focuses the grouped control. Interactive addon content remains responsible for its own native or composed behavior.
Installation
Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.
This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Grouped native controls and addons.
Anatomy
Root styling selector
.input-group
Semantic structure
Use one native input, textarea, select, combobox, or spinbutton inside .input-group. Addons may be placed at inline-start, inline-end, block-start, or block-end with align. Buttons, menus, tooltips, and popovers retain their own behavior.
API
Attributes and state
| Attribute | Access | Purpose |
|---|---|---|
align | Authored | Direct addon placement: inline-start, inline-end, block-start, or block-end. |
aria-invalid | Authored | Validation state exposed to assistive technology and CSS. |
border | Authored | Use true on a direct block addon to draw its dividing border. |
size | Authored | Direct action size: sm, icon-xs, or icon-sm; omit for the compact addon action. |
Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.
CSS custom properties
This styling hook does not define component-specific CSS custom properties.
DOM events
This component does not emit a component-specific custom event.
Native DOM events continue to work normally. AngularTS event directives such as
ng-click and ng-keydown, plus the data-change model callback, remain application-owned.
Behavior
Input Group is styling-only. Native controls own focus, values, validation, and submission. Use a native label addon when clicking addon text should focus the control; AngularTS owns dynamic text and actions.
AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.
Accessibility
Keep one clearly labeled native control in each group. Use aria-describedby for explanatory addon text, aria-hidden for decorative text, and a native label for when an addon should focus the control.
Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.
Customization
Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.
Read Customization for layer order, design tokens, state variants, and iframe demo isolation.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.