Vistaprint

Dropdown

Dropdown is a pull-down list of items that appear when the component is selected; this list remains open until a user selects an item or dismisses the list.

Playground

Size

The "mini" size will make the dropdown shorter than normal.

Share
Share
jsx
<select class="stylized-select stylized-select-mini">
etc
</select>

Rounded

A rounded Dropdown has rounded corners. As of fall 2020, this is now the Visage default, but it might not always be in the future (or when using some themes).

Share
Share
jsx
<select class="stylized-select stylized-select-rounded">
etc
</select>

Borderless

A borderless Dropdown has no visible border around it.

Share
Share
jsx
<select class="stylized-select stylized-select-borderless">
etc
</select>

Skins

There is an "error" skin to indicate there's an error with the current selection. However, in React, you will not need to set this explicitly if you use the FormField component with a FormError; that component will set the error skin for you when an error message is present. See below.

Share
Share
jsx
<select class="stylized-select stylized-select-skin-error">
etc
</select>

Label, Error Message, and Helper Text

Dropdown labels and error text should use the standard Form component.

Vanilla API

See Form for more.

React API

In React, you should make use of the FormField components to add a label, error message, or helper text. These components will automatically add the proper aria attributes to the Dropdown so that you don't need to handle them yourself.

Note that the FormField components don't add much styling on their own, and that you'll probably want to nest the FormField inside of a StandardForm in order to get the desired look.

If you inspect the DOM, you'll see that the FormLabel automatically has its for attribute set to the id of the Dropdown and that the Dropdown's aria-describedby prop is set to the id of the FormHelper.

There is no wrong answer

Share
Share
jsx

Here's an example with an error. Notice that we don't have to add any special props to the Dropdown! The presence of a FormError is enough for the Dropdown to know that it should assume an error-state look. If you inspect the DOM, you'll also find that the aria-errormessage and aria-describedby props on the Dropdown are automatically set.

You must make a selection

Share
Share
jsx

Managing State in React

As is the case with most form elements, folks often want to "control" this component. Controlling a component means that you take ownership over its state rather than letting the browser manage the state for you. When you control a component, you own the source of truth for the UI. This means that you don't need to query the DOM in order to determine the current value of the element. So, when it comes time to use the value of the element somewhere else (e.g. submitting the selection to a back-end service) you can trust your stored value.

If you'd like to control a Dropdown, you'll need store the currently-selected value somewhere (e.g. React state or a Redux store), and you'll need to provide a handler to update that value when the user interacts with the component.

e.g.

jsx
const MyDropdown = props => {
const [selectedValue, setSelectedValue] = React.useState('A')
return (
<Dropdown
value={selectedValue}
onChange={event => setSelectedValue(event.target.value)}
>
<DropdownOption value="A">A</DropdownOption>
<DropdownOption value="B">B</DropdownOption>
<DropdownOption value="C">C</DropdownOption>
</Dropdown>
)
}

If you don't care about the state of the Dropdown, you can simply omit the value and onChange props and let the browser handle the state for you. In this case, you may want to provide the defaultValue prop so that the browser knows which value to select as the initial state.

Components

Dropdown

PropTypeDefaultDescription
skin"line" | "standard" | "error"

The visual variant

Note that error is implied if the TextInput is used inside of a FormInput that also contains a FormError

sizeVariant"standard" | "mini""standard"

size (height) of the dropdown

fullWidthbooleanfalse

Whether or not the Dropdown should expand to fill the entire width of its container

roundedbooleanfalse

Whether or not the Dropdown should have rounded corners

borderlessbooleanfalse

Whether or not the Dropdown should have a border around it

All other props are forwarded to the element specified in thecomponentprop(default: <select/>)

DropdownOption

DropdownOption has no props of its own

All props are forwarded to the element specified in thecomponentprop(default: <option/>)

Implementation Notes

Our dropdown uses (and extends) the native <select> element, rather than try to reproduce its functionality with HTML. This does impose some limits on the styling we can perform on the options inside the dropdown. There are many reasons for using a native dropdown:

  • Since 2019, about half of our sessions are on tablets and phones. Using a native <select> means that phone users get their device's own select experience, which is mobile-optimized. (For instance, iPhone users get the fullscreen "scroll wheel" display.) The browser manufacturers have invested a lot of UX research into determining that this is a good user experience for touch-screen users.

    • Replicating this experience across browsers is complex, and thus costly to maintain. Apple, Google, and Microsoft have invested considerable development and QA time into their versions, which we get to use for free. Building it ourselves would be technically challenging, would require considerable cross-browser and cross-device testing, and we would have a continuous maintenance cost on this going forward.

    • Consider a small screen where the dropdown, when opened, drops down off the bottom edge of the screen. If the user touches the screen to scroll downward to see more choices, that touch will be registered as a click on the dropdown, thus making a selection and closing the dropdown! This is not an easy usability problem to surmount, which is exactly why phone browsers have built their own unique dropdown experiences such as the iOS scroll wheel.

  • Recreating the browser's own built-in functionality always makes for poor performance, both in terms of bandwidth (the browser must download the custom code) and rendering speed (a JavaScript-based dropdown will never react as quickly as the browser's built-in version.) In addition, the custom version won't react to user input as quickly as a native dropdown, making it feel sluggish.

  • The native control automatically has accessibility support across devices, including assistive technologies. Replicating the accessibility features would require even more JavaScript (e.g. supporting keyboard access), creating an even greater negative impact on performance.

  • Any given implementation will create an unfamiliar user experience for some users. For instance, the iPhone Safari dropdown doesn't look or act like the Android Chrome dropdown, so if we made our dropdown look like one of these, users of the other one would have a strange-looking dropdown. The dropdowns on Chrome for Mac don't even look like the ones on Chrome for Windows! The "correct" visual experience on one browser/OS combination will look strange on any other combination, so by using the browser's built-in dropdown, the user always gets a comfortable and familiar user experience.

Guidelines

Designer Guidelines

For usability, the dropdown uses generous padding and a large font. This means that the control does have a certain minimum width (this number depends on the widest option within the dropdown). For this reason, you should be sure to place it in a part of the page that gives it sufficient room to render, including the possibility that translated text might be longer than English text. If it is placed in an area that is too narrow, it may not display properly.

We have limited styling choices for the content of the dropdown's menu items, because we use the browser's native dropdown menu (see "Implementation Notes") to provide an optimal experience on mobile devices and assistive technologies. The browsers don't give you as much styling control as you might want; for instance, we can set the font color, size, and weight, but only for the entire dropdown, not for just one part of it. We cannot use strikethrough text or set any layout inside those dropdown choices.

Developer Guidelines

  • For the vanilla JS API, if your dropdown is created after the DOMready event, you will need initialize it by triggering an initializeControl event on it.

  • We recommend that you not place a dropdown inside an element that is a table cell or has CSS display: table-cell on it, as this can cause the dropdown to be rendered more narrowly than its true minimum width.

Accessibility Guidelines

  • Dropdowns, like any form input field, need an accessible label, preferably a <label> tag, with a for attribute whose value is the id of the dropdown. (If a <label> tag is not possible, the <select> tag either needs a aria-labelledby attribute, or an aria-label attribute with a localized value.)

  • When a dropdown has an error, the error message should not be a <label> tag pointing to the dropdown. Instead, the <select> tag should have aria-describedby and aria-errormessage attributes whose value is the id of the error message. In addition, while the dropdown's value is invalid, the <select> should have aria-invalid="true" on it.

  • If an dropdown is a required field before the user can submit the page, add the attribute aria-required="true" to the <select> tag.