Text input
A text input is a user interface component that allows users to enter or edit textual data. It provides a visual and interactive affordance for text entry while supporting labels, placeholders, icons, helper messages, and validation feedback.
On this page
- Text input v1.3.0
You can find here the OUDS text input design guidelines.
Overview
Use a .text-input wrapper to create a textual form field with OUDS styles, then wrap a pair of <input class="text-input-field"> and <label> elements in .text-input-container. Note that the <label> must come before the <input>.
A placeholder attribute is required on each <input> as our CSS-only floating label implementation relies on the :placeholder-shown pseudo-element to detect when the input is a empty.
Even if you don't need a placeholder, you must always define the placeholder attribute with a single space character. This ensures the label behaves correctly by preventing it from overlapping the input text when a value is entered.
To be compliant with the WCAG 1.3.5: Identify Input Purpose criteria, for each input field collecting information about the user, add the appropriate value to the autocomplete attribute (sufficient technique H98).
<div class="text-input">
<div class="text-input-container">
<label for="exampleTextInputWithEmptyPlaceholder">Email address</label>
<input type="email" autocomplete="email" class="text-input-field" id="exampleTextInputWithEmptyPlaceholder" placeholder=" ">
</div>
</div> If the placeholder text is supplied, <label> will automatically adjust to its floated position.
<div class="text-input">
<div class="text-input-container">
<label for="exampleTextInputWithPlaceholder">Email address</label>
<input type="email" class="text-input-field" id="exampleTextInputWithPlaceholder" placeholder="name@example.com">
</div>
</div> When there’s a value already defined, <label>s will automatically adjust to their floated position.
<div class="text-input">
<div class="text-input-container">
<label for="exampleTextInputWithValue">Input with value</label>
<input type="email" class="text-input-field" id="exampleTextInputWithValue" placeholder="name@example.com" value="test@example.com">
</div>
</div> Variants
Outlined
Add .text-input-container-outlined for a minimalist input with a transparent background and a visible stroke outlining the field. This style may be interesting for contexts other than form pages:
- When inputs need to feel lightweight and unobtrusive
- In a header (search field)
- In a selection/filtering feature in a product catalog
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputOutlined">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputOutlined" placeholder=" ">
</div>
</div> Rounded
Rounded corners inputs is a project-wide option therefore all your inputs should either be rounded or not. Add .use-rounded-corner-inputs on a top container (for example <body>) to use rounded corners.
We use a <div> as a parent container because we cannot use <body> in an example
<div class="use-rounded-corner-inputs">
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputRounded">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputRounded" placeholder=" ">
</div>
</div>
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputRoundedAlt">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputRoundedAlt" placeholder=" ">
</div>
</div>
</div> Leading icon
Add an icon to help indicate the purpose of the input by placing an <svg> or <img> element inside the .text-input-container. The icon is automatically positioned at the left side of the input field.
The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.
<div class="text-input mb-medium">
<div class="text-input-container">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label for="exampleTextInputEmptyWithIcon">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputEmptyWithIcon" placeholder=" ">
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label for="exampleTextInputPlaceholderWithIcon">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputPlaceholderWithIcon" placeholder="placeholder">
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container text-input-container-outlined">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label for="exampleTextInputAltEmptyWithIcon">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputAltEmptyWithIcon" placeholder=" ">
</div>
</div>
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label for="exampleTextInputAltValueWithIcon">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputAltValueWithIcon" placeholder="placeholder" value="Input">
</div>
</div> Trailing action
Trailing actions can be added to the right side of the input field by placing a minimal icon only button (.btn, .btn-minimal and .btn-icon) inside the .text-input-container. It can be used to provide actions related to the field: clear input, toggle password visibility, open a date picker, etc.
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputEmptyWithAction">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputEmptyWithAction" placeholder=" ">
<button class="btn btn-minimal btn-icon">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<span class="visually-hidden">Add to favorites</span>
</button>
</div>
</div>
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputEmptyWithActionOutlined">Label</label>
<input type="email" class="text-input-field" id="exampleTextInputEmptyWithActionOutlined" placeholder=" ">
<button class="btn btn-minimal btn-icon">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<span class="visually-hidden">Add to favorites</span>
</button>
</div>
</div> Helper text
To display a helper text below inputs, add a .helper-text as a sibling of a .text-input-container.
Helper text should be explicitly associated with the text input it relates to using the aria-describedby attribute. This will ensure that assistive technologies—such as screen readers—will announce this helper text when the user focuses or enters the input.
Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.
<div class="text-input">
<div class="text-input-container">
<label for="inputTextPassword">Password</label>
<input type="password" id="inputTextPassword" class="text-input-field" aria-describedby="passwordTextHelpBlock" placeholder=" ">
</div>
<p id="passwordTextHelpBlock" class="helper-text">
Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.
</p>
</div> Helper link
If the helper text is not sufficient, it's possible to offer the user an additional help link. The helper link can also be displayed on its own without helper text.
To display a helper link below inputs, use a standard small link with .link and .link-small classes as a sibling of a .text-input-container.
If a helper link is used in conjunction with a helper text, the aria-describedby attribute should refer to the helper text and the helper link should be referenced by the aria-labelledby attribute.
<div class="text-input mb-medium">
<div class="text-input-container">
<label id="labelTextWithHelperTextLink" for="inputTextWithHelperTextLink">Send your feedback</label>
<input type="text" id="inputTextWithHelperTextLink" aria-describedby="feedbackTextHelpBlock" aria-labelledby="labelTextWithHelperTextLink feedbackTextHelpMore" class="text-input-field" placeholder=" ">
</div>
<p id="feedbackTextHelpBlock" class="helper-text">
Please describe your feedback in a few words.
</p>
<a href="#" id="feedbackTextHelpMore" class="link link-small">
More information
</a>
</div>
<div class="text-input">
<div class="text-input-container">
<label for="inputTextWithHelperLink">Send your feedback</label>
<input type="text" id="inputTextWithHelperLink" aria-describedby="feedbackTextHelpLink" class="text-input-field" placeholder=" ">
</div>
<a href="#" id="feedbackTextHelpLink" class="link link-small">
More information
</a>
</div> Input prefix and suffix
A textual prefix or suffix can be added to an input by wrapping the <input> in a .input-container and adding data-bs-prefix and/or data-bs-suffix attributes to it.
For accessibility purpose the prefix and suffix should be explicitly mentioned in the helper text related to the input by the aria-describedby attribute. This will ensure that assistive technologies—such as screen readers—will announce these additional or already existing elements when the user focuses or enters the input.
Please fill in the complete URL without the protocol (e.g. www.example.com).
Enter your email address without the domain name (e.g. only your username before the @).
Enter your price in Pounds (£) without decimals.
Enter your price in Euro (€) without decimals.
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="inputTextWithPrefix">Enter you website URL</label>
<div class="input-container" data-bs-prefix="https://">
<input type="text" id="inputTextWithPrefix" aria-describedby="prefixTextHelpBlock" class="text-input-field" placeholder=" ">
</div>
</div>
<p id="prefixTextHelpBlock" class="helper-text">
Please fill in the complete URL without the protocol (e.g. www.example.com).
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="inputTextWithSuffix">Email</label>
<div class="input-container" data-bs-suffix="@orange.com">
<input type="email" id="inputTextWithSuffix" aria-describedby="suffixTextHelpBlock" class="text-input-field" placeholder=" ">
</div>
</div>
<p id="suffixTextHelpBlock" class="helper-text">
Enter your email address without the domain name (e.g. only your username before the @).
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="inputTextWithPrefixSuffix">Price</label>
<div class="input-container" data-bs-prefix="£" data-bs-suffix=".00">
<input type="text" id="inputTextWithPrefixSuffix" aria-describedby="prefixSuffixTextHelpBlock" class="text-input-field" placeholder="Enter amount">
</div>
</div>
<p id="prefixSuffixTextHelpBlock" class="helper-text">
Enter your price in Pounds (£) without decimals.
</p>
</div>
<div class="text-input">
<div class="text-input-container">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label for="inputTextWithPrefixSuffixIcon">Price</label>
<div class="input-container" data-bs-prefix="€" data-bs-suffix=".00">
<input type="text" id="inputTextWithPrefixSuffixIcon" aria-describedby="prefixSuffixIconTextHelpBlock" class="text-input-field" placeholder=" ">
</div>
<button class="btn btn-minimal btn-icon">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<span class="visually-hidden">Add to favorites</span>
</button>
</div>
<p id="prefixSuffixIconTextHelpBlock" class="helper-text">
Enter your price in Euro (€) without decimals.
</p>
</div> Layout
Max width
By default text inputs will span the whole width of their parent container, to limit the width of the text input on wider parent container, add a .component-max-width to the .text-input container.
Enter your price in Pounds (£) without decimals.
<div class="text-input component-max-width mb-medium">
<div class="text-input-container">
<label for="exampleTextInputWithMaxWidth">Email address</label>
<input type="email" autocomplete="email" class="text-input-field" id="exampleTextInputWithMaxWidth" placeholder=" ">
</div>
</div>
<div class="text-input component-max-width mb-medium">
<div class="text-input-container">
<label for="exampleTextInputWithMaxWidthSuffix">Price</label>
<div class="input-container" data-bs-prefix="£" data-bs-suffix=".00">
<input type="text" id="exampleTextInputWithMaxWidthSuffix" aria-describedby="prefixSuffixTextHelpBlockMW" class="text-input-field" placeholder="Enter amount">
</div>
</div>
<p id="prefixSuffixTextHelpBlockMW" class="helper-text">
Enter your price in Pounds (£) without decimals.
</p>
</div> States
Disabled
Add the disabled boolean attribute on an input to give it a grayed out appearance, remove pointer events, and prevent focusing.
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputDisabledEmpty">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputDisabledEmpty" placeholder=" " disabled>
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputDisabled">Lastname</label>
<input type="text" class="text-input-field" id="exampleTextInputDisabled" placeholder=" " value="Doe" disabled>
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputOutlinedDisabledEmpty">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputOutlinedDisabledEmpty" placeholder=" " disabled>
</div>
</div>
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputOutlinedDisabled">Lastname</label>
<input type="text" class="text-input-field" id="exampleTextInputOutlinedDisabled" placeholder=" " value="Doe" disabled>
</div>
</div> Readonly
Add the readonly boolean attribute on an input to prevent modification of the input’s value. readonly inputs can still be focused and selected, while disabled inputs cannot.
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputReadonlyEmpty">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputReadonlyEmpty" placeholder=" " readonly>
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<label for="exampleTextInputReadonly">Lastname</label>
<input type="text" class="text-input-field" id="exampleTextInputReadonly" placeholder=" " value="Doe" readonly>
</div>
</div>
<div class="text-input mb-medium">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputOutlinedReadonlyEmpty">Firstname</label>
<input type="text" class="text-input-field" id="exampleTextInputOutlinedReadonlyEmpty" placeholder=" " readonly>
</div>
</div>
<div class="text-input">
<div class="text-input-container text-input-container-outlined">
<label for="exampleTextInputOutlinedReadonly">Lastname</label>
<input type="text" class="text-input-field" id="exampleTextInputOutlinedReadonly" placeholder=" " value="Doe" readonly>
</div>
</div> Invalid
The invalid state is the equivalent of the ‘Error’ state that you can find in the design specification.
To display an invalid input, add .is-invalid to a .text-input-field within the .text-input-container. Please take a look at our Validation page to learn more.
For accessibility purposes, the invalid state should be associated with a .error-text as a sibling of a .text-input-container and related to it with an aria-labelledby attribute when displayed. Note that the .error-text will replace the helper text, so it should be descriptive enough to convey the error.
Please choose a username.
Username is required.
Email is invalid.
Address is required.
City is invalid.
Price is not valid.
<div class="text-input mb-medium">
<div class="text-input-container">
<label id="labelTextInputInvalidEmpty" for="exampleTextInputInvalidEmpty">Username</label>
<input type="text" class="text-input-field is-invalid" id="exampleTextInputInvalidEmpty" aria-describedby="usernameTextHelpBlock" aria-labelledby="labelTextInputInvalidEmpty usernameFeedback" placeholder=" ">
</div>
<p id="usernameTextHelpBlock" class="helper-text">
Please choose a username.
</p>
<p id="usernameFeedback" class="error-text">
Username is required.
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<label id="labelTextInputInvalid" for="exampleTextInputInvalid">Email</label>
<input type="text" class="text-input-field is-invalid" id="exampleTextInputInvalid" value="john.doe@example" aria-labelledby="labelTextInputInvalid emailFeedback" placeholder=" ">
<button class="btn btn-minimal btn-icon">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<span class="visually-hidden">Add to favorites</span>
</button>
</div>
<p id="emailFeedback" class="error-text">
Email is invalid.
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container text-input-container-outlined">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label id="labelTextInputOutlinedInvalidEmpty" for="exampleTextInputOutlinedInvalidEmpty">Address</label>
<input type="text" class="text-input-field is-invalid" id="exampleTextInputOutlinedInvalidEmpty" aria-labelledby="labelTextInputOutlinedInvalidEmpty addressFeedback" placeholder=" ">
</div>
<p id="addressFeedback" class="error-text">
Address is required.
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container text-input-container-outlined">
<label id="labelTextInputOutlinedInvalid" for="exampleTextInputOutlinedInvalid">City</label>
<input type="text" class="text-input-field is-invalid" id="exampleTextInputOutlinedInvalid" value="Doe" aria-labelledby="labelTextInputOutlinedInvalid cityFeedback" placeholder=" ">
</div>
<p id="cityFeedback" class="error-text">
City is invalid.
</p>
</div>
<div class="text-input mb-medium">
<div class="text-input-container">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label id="labelTextInputInvalidWithPrefixSuffix" for="exampleTextInputInvalidWithPrefixSuffix">Price</label>
<div class="input-container" data-bs-prefix="£" data-bs-suffix=".00">
<input type="text" class="text-input-field is-invalid" id="exampleTextInputInvalidWithPrefixSuffix" value="-2.2XX" aria-labelledby="labelTextInputInvalidWithPrefixSuffix priceFeedback" placeholder=" ">
</div>
</div>
<p id="priceFeedback" class="error-text">
Price is not valid.
</p>
</div>
<div class="text-input">
<div class="text-input-container">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#heart-empty"/>
</svg>
<label id="labelTextInputInvalidTrailingWithPrefixSuffix" for="exampleTextInputInvalidTrailingWithPrefixSuffix">Price</label>
<div class="input-container" data-bs-prefix="£" data-bs-suffix=".00">
<input type="text" class="text-input-field is-invalid" id="exampleTextInputInvalidTrailingWithPrefixSuffix" value="-2.2XX" aria-describedby="priceTextHelpBlock" aria-labelledby="labelTextInputInvalidTrailingWithPrefixSuffix invalidPrice" placeholder=" ">
</div>
<button class="btn btn-minimal btn-icon">
<svg aria-hidden="true">
<use xlink:href="/orange/docs/0.6/assets/img/ouds-web-sprite.svg#trash"/>
</svg>
<span class="visually-hidden">Delete</span>
</button>
</div>
<p id="priceTextHelpBlock" class="helper-text">
Please enter your price.
</p>
<p id="invalidPrice" class="error-text">
Price is not valid.
</p>
<a href="#" id="priceTextHelpLink" class="link link-small">
More information
</a>
</div>