Forms
The <FormControl>
component renders a form control with Bootstrap styling. The <FormGroup>
component wraps a form control with proper spacing, along with support for a label, help text, and validation state. To ensure accessibility, set controlId
on <FormGroup>
, and use <FormLabel>
for the label.
<Form> <Form.Group controlId="formBasicEmail"> <Form.Label>Email address</Form.Label> <Form.Control type="email" placeholder="Enter email" /> <Form.Text className="text-muted"> We'll never share your email with anyone else. </Form.Text> </Form.Group> <Form.Group controlId="formBasicPassword"> <Form.Label>Password</Form.Label> <Form.Control type="password" placeholder="Password" /> </Form.Group> <Form.Group controlId="formBasicChecbox"> <Form.Check type="checkbox" label="Check me out" /> </Form.Group> <Button variant="primary" type="submit"> Submit </Button> </Form>;
The <FormControl>
component directly renders the <input>
or other specified component. If you need to access the value of an uncontrolled <FormControl>
, attach a ref
to it as you would with an uncontrolled input, then call ReactDOM.findDOMNode(ref)
to get the DOM node. You can then interact with that node as you would with any other uncontrolled input.
If your application contains a large number of form groups, we recommend building a higher-level component encapsulating a complete field group that renders the label, the control, and any other necessary components. We don't provide this out-of-the-box, because the composition of those field groups is too specific to an individual application to admit a good one-size-fits-all solution.
Form controls
For textual form controls—like input
s, select
s, and textarea
s—use the FormControl
component. FormControl adds some additional styles for general appearance, focus state, sizing, and more.
<Form> <Form.Group controlId="exampleForm.ControlInput1"> <Form.Label>Email address</Form.Label> <Form.Control type="email" placeholder="name@example.com" /> </Form.Group> <Form.Group controlId="exampleForm.ControlSelect1"> <Form.Label>Example select</Form.Label> <Form.Control as="select"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </Form.Control> </Form.Group> <Form.Group controlId="exampleForm.ControlSelect2"> <Form.Label>Example multiple select</Form.Label> <Form.Control as="select" multiple> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </Form.Control> </Form.Group> <Form.Group controlId="exampleForm.ControlTextarea1"> <Form.Label>Example textarea</Form.Label> <Form.Control as="textarea" rows="3" /> </Form.Group> </Form>;
Sizing
Use size
on <FormControl>
to change the size of inputs.
<> <Form.Control size="lg" type="text" placeholder="Large text" /> <br /> <Form.Control type="text" placeholder="Normal text" /> <br /> <Form.Control size="sm" type="text" placeholder="Small text" /> </>;
Plaintext
If you want to have elements in your form styled as plain text, use the plaintext
prop on FormControls to remove the default form field styling and preserve the correct margin and padding.
<Form> <Form.Group as={Row} controlId="formPlaintextEmail"> <Form.Label column sm="2"> Email </Form.Label> <Col sm="10"> <Form.Control plaintext readOnly defaultValue="email@example.com" /> </Col> </Form.Group> <Form.Group as={Row} controlId="formPlaintextPassword"> <Form.Label column sm="2"> Password </Form.Label> <Col sm="10"> <Form.Control type="password" placeholder="Password" /> </Col> </Form.Group> </Form>;
Checkboxes and Radios
For the non-textual checkbox and radio controls, FormCheck
provides a single component for both types that adds some additional styling and improved layout.
Default (stacked)
By default, any number of checkboxes and radios that are immediate sibling will be vertically stacked and appropriately spaced with FormCheck.
<Form> {['checkbox', 'radio'].map(type => ( <div key={`default-${type}`} className="mb-3"> <Form.Check type={type} id={`default-${type}`} label={`default ${type}`} /> <Form.Check disabled type={type} label={`disabled ${type}`} id={`disabled-default-${type}`} /> </div> ))} </Form>;
Inline
Group checkboxes or radios on the same horizontal row by adding the inline
prop.
<Form> {['checkbox', 'radio'].map(type => ( <div key={`inline-${type}`} className="mb-3"> <Form.Check inline label="1" type={type} id={`inline-${type}-1`} /> <Form.Check inline label="2" type={type} id={`inline-${type}-2`} /> <Form.Check inline disabled label="3 (disabled)" type={type} id={`inline-${type}-3`} /> </div> ))} </Form>;
Without labels
When you render a FormCheck without a label (no children
) some additional styling is applied to keep the inputs from collapsing. Remember to add an aria-label
when omitting labels!
<> <Form.Check aria-label="option 1" /> <Form.Check type="radio" aria-label="radio 1" /> </>;
Customizing FormCheck rendering
When you need tighter control, or want to customize how the FormCheck
component renders, it may better to use it's constituent parts directly.
By provided children
to the FormCheck
you can forgo the default rendering and handle it yourself. (You can still provide an id
to the FormCheck
or FormGroup
and have it propogate to the label and input).
<Form> {['checkbox', 'radio'].map(type => ( <div key={type} className="mb-3"> <Form.Check type={type} id={`check-api-${type}`}> <Form.Check.Input type={type} isValid /> <Form.Check.Label>{`Custom api ${type}`}</Form.Check.Label> <Form.Control.Feedback type="valid">You did it!</Form.Control.Feedback> </Form.Check> </div> ))} </Form>;
Layout
FormControl and FormCheck both apply display: block
with width: 100%
to controls, which means they stack vertically by default. Additional components and props can be used to vary this layout on a per-form basis.
Form group
The FormGroup
component is the easiest way to add some structure to forms. It provides a flexible container for grouping of labels, controls, optional help text, and form validation messaging. By default it only applies margin-bottom, but it picks up additional styles in <Form inline >
as needed. Use it with fieldset
s, div
s, or nearly any other element.
You also add the controlId
prop to accessibly wire the nested label and input together via the id
.
<Form> <Form.Group controlId="formGroupEmail"> <Form.Label>Email address</Form.Label> <Form.Control type="email" placeholder="Enter email" /> </Form.Group> <Form.Group controlId="formGroupPassword"> <Form.Label>Password</Form.Label> <Form.Control type="password" placeholder="Password" /> </Form.Group> </Form>;
Form grid
More complex forms can be built using the grid components. Use these for form layouts that require multiple columns, varied widths, and additional alignment options.
<Form> <Row> <Col> <Form.Control placeholder="First name" /> </Col> <Col> <Form.Control placeholder="Last name" /> </Col> </Row> </Form>;
Form row
You may also swap <Row>
for <Form.Row>
, a variation of the standard grid row that overrides the default column gutters for tighter and more compact layouts.
<Form> <Form.Row> <Col> <Form.Control placeholder="First name" /> </Col> <Col> <Form.Control placeholder="Last name" /> </Col> </Form.Row> </Form>;
More complex layouts can also be created with the grid system.
<Form> <Form.Row> <Form.Group as={Col} controlId="formGridEmail"> <Form.Label>Email</Form.Label> <Form.Control type="email" placeholder="Enter email" /> </Form.Group> <Form.Group as={Col} controlId="formGridPassword"> <Form.Label>Password</Form.Label> <Form.Control type="password" placeholder="Password" /> </Form.Group> </Form.Row> <Form.Group controlId="formGridAddress1"> <Form.Label>Address</Form.Label> <Form.Control placeholder="1234 Main St" /> </Form.Group> <Form.Group controlId="formGridAddress2"> <Form.Label>Address 2</Form.Label> <Form.Control placeholder="Apartment, studio, or floor" /> </Form.Group> <Form.Row> <Form.Group as={Col} controlId="formGridCity"> <Form.Label>City</Form.Label> <Form.Control /> </Form.Group> <Form.Group as={Col} controlId="formGridState"> <Form.Label>State</Form.Label> <Form.Control as="select"> <option>Choose...</option> <option>...</option> </Form.Control> </Form.Group> <Form.Group as={Col} controlId="formGridZip"> <Form.Label>Zip</Form.Label> <Form.Control /> </Form.Group> </Form.Row> <Form.Group id="formGridCheckbox"> <Form.Check type="checkbox" label="Check me out" /> </Form.Group> <Button variant="primary" type="submit"> Submit </Button> </Form>;
Horizontal forms
You may also swap <Row>
for <Form.Row>
, a variation of the standard grid row that overrides the default column gutters for tighter and more compact layouts.
<Form> <Form.Group as={Row} controlId="formHorizontalEmail"> <Form.Label column sm={2}> Email </Form.Label> <Col sm={10}> <Form.Control type="email" placeholder="Email" /> </Col> </Form.Group> <Form.Group as={Row} controlId="formHorizontalPassword"> <Form.Label column sm={2}> Password </Form.Label> <Col sm={10}> <Form.Control type="password" placeholder="Password" /> </Col> </Form.Group> <fieldset> <Form.Group as={Row}> <Form.Label as="legend" column sm={2}> Radios </Form.Label> <Col sm={10}> <Form.Check type="radio" label="first radio" name="formHorizontalRadios" id="formHorizontalRadios1" /> <Form.Check type="radio" label="second radio" name="formHorizontalRadios" id="formHorizontalRadios2" /> <Form.Check type="radio" label="third radio" name="formHorizontalRadios" id="formHorizontalRadios3" /> </Col> </Form.Group> </fieldset> <Form.Group as={Row} controlId="formHorizontalCheck"> <Col sm={{ span: 10, offset: 2 }}> <Form.Check label="Remember me" /> </Col> </Form.Group> <Form.Group as={Row}> <Col sm={{ span: 10, offset: 2 }}> <Button type="submit">Sign in</Button> </Col> </Form.Group> </Form>;
Validation
Provide valuable, actionable feedback to your users with form validation feedback.
Native HTML5 form validation
For native HTML form validation–available in all our supported browsers, the :valid
and :invalid
pseudo selectors are used to apply validation styles as well as display feedback messages.
Bootstrap scopes the :valid
and :invalid
styles to parent .was-validated
class, usually applied to the Form
(you can use the validated
prop as a shortcut). Otherwise, any required field without a value shows up as invalid on page load. This way, you may choose when to activate them (typically after form submission is attempted).
class FormExample extends React.Component { constructor(...args) { super(...args); this.state = { validated: false }; } handleSubmit(event) { const form = event.currentTarget; if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } this.setState({ validated: true }); } render() { const { validated } = this.state; return ( <Form noValidate validated={validated} onSubmit={e => this.handleSubmit(e)} > <Form.Row> <Form.Group as={Col} md="4" controlId="validationCustom01"> <Form.Label>First name</Form.Label> <Form.Control required type="text" placeholder="First name" defaultValue="Mark" /> <Form.Control.Feedback>Looks good!</Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="4" controlId="validationCustom02"> <Form.Label>Last name</Form.Label> <Form.Control required type="text" placeholder="Last name" defaultValue="Otto" /> <Form.Control.Feedback>Looks good!</Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="4" controlId="validationCustomUsername"> <Form.Label>Username</Form.Label> <InputGroup> <InputGroup.Prepend> <InputGroup.Text id="inputGroupPrepend">@</InputGroup.Text> </InputGroup.Prepend> <Form.Control type="text" placeholder="Username" aria-describedby="inputGroupPrepend" required /> <Form.Control.Feedback type="invalid"> Please choose a username. </Form.Control.Feedback> </InputGroup> </Form.Group> </Form.Row> <Form.Row> <Form.Group as={Col} md="6" controlId="validationCustom03"> <Form.Label>City</Form.Label> <Form.Control type="text" placeholder="City" required /> <Form.Control.Feedback type="invalid"> Please provide a valid city. </Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="3" controlId="validationCustom04"> <Form.Label>State</Form.Label> <Form.Control type="text" placeholder="State" required /> <Form.Control.Feedback type="invalid"> Please provide a valid state. </Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="3" controlId="validationCustom05"> <Form.Label>Zip</Form.Label> <Form.Control type="text" placeholder="Zip" required /> <Form.Control.Feedback type="invalid"> Please provide a valid zip. </Form.Control.Feedback> </Form.Group> </Form.Row> <Form.Group> <Form.Check required label="Agree to terms and conditions" feedback="You must agree before submitting." /> </Form.Group> <Button type="submit">Submit form</Button> </Form> ); } } render(<FormExample />);
Form libraries and server rendered styles.
It's often beneficial (especially in React) to handle form validation via a library like Formik, or react-formal. In those cases, isValid
and isInvalid
props can be added to form controls to manually apply validation styles. Below is a quick example integrating with Formik.
const { Formik } = formik; const schema = yup.object({ firstName: yup.string().required(), lastName: yup.string().required(), username: yup.string().required(), city: yup.string().required(), state: yup.string().required(), zip: yup.string().required(), terms: yup.bool().required(), }); function FormExample() { return ( <Formik validationSchema={schema} onSubmit={console.log} initialValues={{ firstName: 'Mark', lastName: 'Otto', }} > {({ handleSubmit, handleChange, handleBlur, values, touched, isValid, errors, }) => ( <Form noValidate onSubmit={handleSubmit}> <Form.Row> <Form.Group as={Col} md="4" controlId="validationFormik01"> <Form.Label>First name</Form.Label> <Form.Control type="text" name="firstName" value={values.firstName} onChange={handleChange} isValid={touched.firstName && !errors.firstName} /> <Form.Control.Feedback>Looks good!</Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="4" controlId="validationFormik02"> <Form.Label>Last name</Form.Label> <Form.Control type="text" name="lastName" value={values.lastName} onChange={handleChange} isValid={touched.firstName && !errors.lastName} /> <Form.Control.Feedback>Looks good!</Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="4" controlId="validationFormikUsername"> <Form.Label>Username</Form.Label> <InputGroup> <InputGroup.Prepend> <InputGroup.Text id="inputGroupPrepend">@</InputGroup.Text> </InputGroup.Prepend> <Form.Control type="text" placeholder="Username" aria-describedby="inputGroupPrepend" name="username" value={values.username} onChange={handleChange} isInvalid={!!errors.username} /> <Form.Control.Feedback type="invalid"> {errors.username} </Form.Control.Feedback> </InputGroup> </Form.Group> </Form.Row> <Form.Row> <Form.Group as={Col} md="6" controlId="validationFormik03"> <Form.Label>City</Form.Label> <Form.Control type="text" placeholder="City" name="city" value={values.city} onChange={handleChange} isInvalid={!!errors.city} /> <Form.Control.Feedback type="invalid"> {errors.city} </Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="3" controlId="validationFormik04"> <Form.Label>State</Form.Label> <Form.Control type="text" placeholder="State" name="state" value={values.state} onChange={handleChange} isInvalid={!!errors.state} /> <Form.Control.Feedback type="invalid"> {errors.state} </Form.Control.Feedback> </Form.Group> <Form.Group as={Col} md="3" controlId="validationFormik05"> <Form.Label>Zip</Form.Label> <Form.Control type="text" placeholder="Zip" name="zip" value={values.zip} onChange={handleChange} isInvalid={!!errors.zip} /> <Form.Control.Feedback type="invalid"> {errors.zip} </Form.Control.Feedback> </Form.Group> </Form.Row> <Form.Group> <Form.Check required name="terms" label="Agree to terms and conditions" onChange={handleChange} isInvalid={!!errors.terms} feedback={errors.terms} id="validationFormik0" /> </Form.Group> <Button type="submit">Submit form</Button> </Form> )} </Formik> ); } render(<FormExample />);
Examples
Custom forms
For even more customization and cross browser consistency, use our completely custom form elements to replace the browser defaults. They’re built on top of semantic and accessible markup, so they’re solid replacements for any default form control.
Checkboxes and radios
Custom checkbox and radio styles are achieved with a resourceful use of the :checked
selector and :after
psuedo elements, but are Structurally similar to the default FormCheck
. By default the checked and indeterminate icons use embedded svg icons from Open Iconic.
Apply Bootstrap's custom elements by adding the custom
prop.
<Form> {['checkbox', 'radio'].map(type => ( <div key={`custom-${type}`} className="mb-3"> <Form.Check custom type={type} id={`custom-${type}`} label={`Check this custom ${type}`} /> <Form.Check custom disabled type={type} label={`disabled ${type}`} id={`disabled-custom-${type}`} /> </div> ))} </Form>;
Inline
<Form> {['checkbox', 'radio'].map(type => ( <div key={`custom-inline-${type}`} className="mb-3"> <Form.Check custom inline label="1" type={type} id={`custom-inline-${type}-1`} /> <Form.Check custom inline label="2" type={type} id={`custom-inline-${type}-2`} /> <Form.Check custom inline disabled label="3 (disabled)" type={type} id={`custom-inline-${type}-3`} /> </div> ))} </Form>;
API
Formview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
as | elementType | <form> | You can use a custom element type for this component. |
inline | boolean | false | Display the series of labels, form controls, and buttons on a single horizontal row |
innerRef | ReactRef | The Form | |
validated | boolean | Mark a form as having been validated. Setting it to | |
bsPrefix | string | {'form'} | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
Form.Rowview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
as | elementType | <div> | You can use a custom element type for this component. |
bsPrefix required | string | 'form-row' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
Form.Groupview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
as | elementType | <div> | You can use a custom element type for this component. |
controlId | string | Sets | |
innerRef | ReactRef | The FormGroup | |
bsPrefix | string | 'form-group' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
Form.Labelview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
column | boolean | false | Renders the FormLabel as a |
htmlFor | string | Uses | |
innerRef | ReactRef | The FormLabel | |
srOnly | boolean | false | Hides the label visually while still allowing it to be read by assistive technologies. |
bsPrefix | string | 'form-label' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
Form.Controlview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
as | 'input' | 'textarea' | elementType | 'input' | The underlying HTML element to use when rendering the FormControl. |
disabled | boolean | Make the control disabled | |
id | string | Uses | |
isInvalid | boolean | Add "invalid" validation styles to the control and accompanying label | |
isValid | boolean | Add "valid" validation styles to the control | |
onChange | function | A callback fired when the | |
plaintext | boolean | Render the input as plain text. Generally used along side | |
readOnly | boolean | Make the control readonly | |
ref | ReactRef | The FormControl | |
size | 'sm' | 'lg' | Input size variants | |
type | string | The HTML input | |
value | string | controlled by: onChange , initial prop: defaultValue The | |
bsPrefix | string | {'form-control'} | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
FormControl.Feedbackview source file
import FormControl from 'react-bootstrap/FormControl'
Name | Type | Default | Description |
---|---|---|---|
as | elementType | <div> | You can use a custom element type for this component. |
type | 'valid' | 'invalid' | 'valid' | Specify whether the feedback is for valid or invalid fields |
Form.Checkview source file
import Form from 'react-bootstrap/Form'
Name | Type | Default | Description |
---|---|---|---|
children | node | Provide a function child to manually handle the layout of the FormCheck's inner components.
| |
custom | boolean | Use Bootstrap's custom form elements to replace the browser defaults | |
disabled | boolean | false | |
feedback | node | A message to display when the input is in a validation state | |
id | string | A HTML id attribute, necessary for proper form accessibility. | |
inline | boolean | false | |
inputRef | ReactRef | The FormCheck | |
isInvalid | boolean | false | Manually style the input as invalid |
isValid | boolean | false | Manually style the input as valid |
label | node | ||
title | string | '' | |
type | 'radio' | 'checkbox' | 'checkbox' | The type of checkable. |
bsPrefix | string | 'form-check' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
FormCheck.Inputview source file
import FormCheck from 'react-bootstrap/FormCheck'
Name | Type | Default | Description |
---|---|---|---|
id | string | A HTML id attribute, necessary for proper form accessibility. | |
isInvalid required | boolean | Manually style the input as invalid | |
isStatic | boolean | A convenience prop shortcut for adding | |
isValid required | boolean | Manually style the input as valid | |
type | 'radio' | 'checkbox' | 'checkbox' | The type of checkable. |
bsPrefix | string | 'form-check-input' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |
FormCheck.Labelview source file
import FormCheck from 'react-bootstrap/FormCheck'
Name | Type | Default | Description |
---|---|---|---|
htmlFor | string | The HTML for attribute for associating the label with an input | |
bsPrefix | string | 'form-check-input' | Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css. |