Intelligent CSS Components

Install

Skin is eBay's official CSS framework and is distributed via NPM under the @ebay/skin package name.

To use Skin, the package should be added as a dependency in your project's package.json file.

{
    "dependencies": {
      "@ebay/skin": "^7"
    }
}
    

Lasso

Skin is optimised for use with Lasso.js - an advanced JavaScript module bundler, asset pipeline and optimizer.

Add the @ebay/skin module as a browser.json dependency to include the entire set of Skin modules.

{
    "dependencies": [
        "@ebay/skin"
    ]
}
    

Or, alternatively, by specifying modules on a per-need basis.

{
    "dependencies": [
        "@ebay/skin/less",
        "@ebay/skin/global",
        "@ebay/skin/button",
        "@ebay/skin/icon/foreground"
    ]
}
    

Skin provides the following modules:

Design System

Skin has the ability to switch between previous, current and upcoming design systems.

DS4 is currently the default design system. To opt into DS6, Lasso.js requires the skin-ds6 conditional dependency flag.

myLasso.lassoPage({
    flags: ['skin-ds6']
});
    

Or, alternatively, using the Marko Taglib.

<lasso-page flags=['skin-ds6']>
   ...
</lasso-page>
    

IMPORTANT: There are some differences, in terms of HTML structure and class names, between design system versions; therefore be sure to reference the appropriate documentation. In general we try to minimise these differences, but in some cases it cannot be avoided.

Bundles

Bundles are special Lasso.js modules that bundle together a collection of related Skin components.

@ebay/skin/core

The core module bundles together Skin's core dependencies.

@ebay/skin/combo

The combo module bundles together Skin's most common modules, as identified across key eBay experiences.

Note: The combo bundle itself contains two other bundles. Lasso will take care of de-duping modules where necessary.

@ebay/skin/form

The form module bundles together all form controls and field layout.

@ebay/skin/icon

The icon module bundles together both types of icon: background and foreground.

CDN

A CSS file containing the full collection of modules (except background icon data-urls) is available via the following url:

https://ir.ebaystatic.com/cr/v/c1/skin/v7.2.0/ds4/skin.min.css

Due to their large size, background icon data-urls are considered optional, and are available separately via the following url:

https://ir.ebaystatic.com/cr/v/c1/skin/v7.2.0/ds4/skin-base64.min.css

@ebay/skin/actionable

Actionable Icon

Use the icon-btn class (for buttons) or the icon-link class (for links) and any of the available icons for a borderless, actionable icon style.

<button class="icon-btn" type="button" aria-label="Menu">
    <svg class="icon icon--menu" focusable="false" width="16" height="16" aria-hidden="true">
        <use xlink:href="#icon-menu"></use>
    </svg>
</button>
<a class="icon-link" href="http://www.ebay.com" aria-label="Settings">
    <svg class="icon icon--settings" focusable="false" width="16" height="16" aria-hidden="true">
        <use xlink:href="#icon-settings"></use>
    </svg>
</a>
    

Actionable Image

Use the img-btn class (for buttons) or the img-link class (for links) to create an actionable image-tile effect on hover, focus and active states.

iPhone
<button type="button" class="img-btn">
    <img src="http://i2.ebayimg.com/images/g/e0oAAOSwsN9W~YBY/s-l200.jpg" alt="iPhone" />
</button>
<a href="http://www.ebay.com/sch/i.html?_nkw=iphone" class="img-link">
    <img src="http://i2.ebayimg.com/images/g/e0oAAOSwsN9W~YBY/s-l200.jpg" alt="iPhone" />
</a>
    

@ebay/skin/badge

A badge is a visual indicator added to an element to convey quantity, newness or both. Badges are intended to remind a user of previous actions taken, or to alert them of new actions that they should consider.

Default Badge

The default badge contains the basic, base styles. A role and aria-label are added for assistive technology.

1
<span class="badge" role="img" aria-label="1 notification">1</span>
    

Menu Badge

A badge can be placed inside of a menu item and it will receive the appropriate margin. Note that the aria-label is now moved to the menuitem role.

<span class="menu">
    <div class="menu__items" role="menu">
        <div aria-label="Item 1 (3 notifications)" class="menu__item" role="menuitem">
            <span aria-hidden="true">Item 1<span class="badge">3</span></span>
        </div>
        <div aria-label="Item 2 (77 notifications)" class="menu__item" role="menuitem">
            <span aria-hidden="true">Item 2<span class="badge">77</span></span>
        </div>
        <div class="menu__item" role="menuitem">
            <span>Item 3</span>
        </div>
    </div>
</span>
    

Icon Button Badge

A badge can be placed inside of an icon button and it will receive the appropriate positioning. Note that the aria-label is now moved to the button role.

The button element requires an additional icon-btn--badged modifier.

<button aria-label="Menu (4 notifications)" class="icon-btn icon-btn--badged" type="button">
    <svg class="icon icon--menu" focusable="false" width="16" height="16" aria-hidden="true">
        <use xlink:href="#icon-menu"></use>
    </svg>
    <span aria-hidden="true" class="badge">4</span>
</button>
    

@ebay/skin/button

A button is typically used to trigger a JavaScript action (e.g. fetch results, open a dialog or expand a menu). In this case, the <button> tag is required.

A button may also be used to submit or reset a form. In this case use the <button> tag with type=submit or type=reset respectively. Use of the <input> tag is not currently supported.

Finally, a link may be styled to look like a button. We call this a fake button. In this case the <a> tag is required with a valid HREF attribute.

Raw Button

Use the raw button as the base to build custom modifiers. The raw button does not define any styles for states such as disabled, invalid, readonly, etc.

Link
<button class="btn">Button</button>
<a class="fake-btn" href="http://www.ebay.com">Link</a>
        

Regular Button

Use the regular modifier to create the regular button.

Link
<button class="btn btn--regular">Button</button>
<a class="fake-btn fake-btn--regular" href="http://www.ebay.com">Link</a>
    

Primary Button

Use the primary block modifier to create a primary button style.

Link
<button class="btn btn--primary">Button</button>
<a class="fake-btn fake-btn--primary" href="http://www.ebay.com">Link</a>
        

Secondary Button

Use the secondary block modifier to create a secondary button style.

Link
<button class="btn btn--secondary">Button</button>
<a class="fake-btn fake-btn--secondary" href="http://www.ebay.com">Link</a>
        

Disabled Button

The disabled attribute is required to fully disable a button tag.

<button class="btn btn--primary" type="button" disabled>Primary Button</button>
<button class="btn btn--secondary" type="button" disabled>Secondary Button</button>
    

Remove the href attribute to fully disable an anchor tag.

<a class="fake-btn fake-btn--primary">Primary Link</a>
<a class="fake-btn fake-btn--secondary">Secondary Link</a>
    

Partially Disabled Button

Partially disabled buttons are visually and aurally identifiable as disabled, but remain keyboard focusable.

Partially disabled buttons can vastly simplify keyboard focus management logic in situations where the button may frequently toggle back and forth between enabled and disabled (e.g. pagination or carousel 'bookend' buttons).

The aria-disabled state is required for partially disabled buttons.

<button aria-disabled="true" class="btn btn--primary" type="button">Prev</button>
<button aria-disabled="true" class="btn btn--primary" type="button">Next</button>
    

Fluid Button

Use the btn--fluid modifier to fill the entire width of the parent element.

<button class="btn btn--primary btn--fluid" type="button">Button</button>
    

Small Button (DS4 only)

Use the btn--small size modifier to create a small button style.

<button class="btn btn--primary btn--small">Button</button>
        

Large Button

Use the btn--large size modifier to create a large button style.

<button class="btn btn--primary btn--large" type="button">Button</button>
    

Extra-Large Button (DS4 only)

Use the btn--extra-large size modifier to create an extra large button style.

<button class="btn btn--primary btn--extra-large" type="button">Button</button>
    

Icon Button

Any foreground icon can be placed adjacent to the button text.

<button class="btn btn--primary">
    <span class="btn__cell">
        <svg aria-hidden="true" class="btn__icon" focusable="false" height="16" width="16">
            <use xlink:href="#icon-menu"></use>
        </svg>
        <span>Button</span>
    </span>
</button>
        

To flip position of text and icon, simply swap the DOM order.

<button class="btn btn--primary">
    <span class="btn__cell">
        <span>Button</span>
        <svg aria-hidden="true" class="btn__icon" focusable="false" height="16" width="16">
            <use xlink:href="#icon-menu"></use>
        </svg>
    </span>
</button>
        

Because the button cell uses flex box layout, it is fairly trivial to achieve alternate layouts, as in the example below.

<button class="btn btn--primary btn--fluid" type="button" style="padding-left: 16px; padding-right: 16px;">
    <span class="btn__cell" style="justify-content: space-between">
        <span>Select</span>
        <span style="display: inline-flex;">
            <span>Any</span>
            <svg aria-hidden="true" class="btn__icon" focusable="false" width="8" height="8">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </span>
    </span>
</button>
    

Button wrapping and overflow behavior

Text of buttons will wrap when the button fills it's constrained width (if any).

<div style="max-width 200px;">
    <button class="btn">
        Button with a lot of text that will wrap
    </button>
</div>
    

To apply a fixed height to a button use the following pattern: btn--medium-fixed-height.

<div style="max-width 200px;">
    <button class="btn btn--medium-fixed-height">
        Button with a lot of text that will wrap
    </button>
</div>
    
<button class="btn btn--medium-fixed-height">
    Button with a lot of text that won't wrap
</button>
    

To apply truncation to text use the following pattern: btn--medium-truncated.

<div style="max-width 200px;">
    <button class="btn btn--medium-truncated">
        Button with a lot of text that will wrap
    </button>
</div>
    

Pill Button

Use the pill modifier to create a button styled as a pill. It should be used in conjunction with primary/secondary modifiers for full styling. Note that the pill only supports one size, so it should not be used together with sizing modifiers. Additionally, JavaScript should be used for multi-line ellipsis truncation.

Default Pill

Link
<button class="btn btn--pill">Button</button>
<a class="fake-btn fake-btn--pill" href="http://www.ebay.com">Link</a>
    

Selected Pill

<button class="btn btn--primary btn--pill" aria-pressed="true">Button</button>
<a class="fake-btn fake-btn--primary fake-btn--pill" href="http://www.ebay.com">Link<span class="clipped"> - Selected</span></a>
    

Unselected Pill

Link
<button class="btn btn--secondary btn--pill">Button</button>
<a class="fake-btn fake-btn--secondary fake-btn--pill" href="http://www.ebay.com">Link</a>
    

Multiline Pill

Link with two lines of text
<button class="btn btn--secondary btn--pill">Button with two lines of text</button>
<a class="fake-btn fake-btn--secondary fake-btn--pill" href="http://www.ebay.com">Link with two lines of text</a>
    

Note: Adding a btn--medium-truncated class (or similar classes) to the pill has undesired results. A better solution is to truncate the text with JavaScript while adding the necessary accessibility attributes to satisfy accessibility requirements.

Expand Button

Use the expand-btn base class on a button that expands (and collapses) content.

<button aria-expanded="false" class="expand-btn expand-btn--primary" type="button">
    <span class="expand-btn__cell">
        <span>Expand</span>
        <span class="expand-btn__icon"></span>
    </span>
</button>
        

Can be used with or without a text label, with background or foreground SVG.

<button aria-expanded="false" class="expand-btn expand-btn--primary expand-btn--no-text" aria-label="Expand/Collapse">
    <span class="expand-btn__icon"></span>
</button>
        

CTA Button

Takes users to another URL destination (i.e. it is always a hyperlink).

Default Background

<a class="cta-btn" href="http://www.ebay.com">
    <span class="cta-btn__cell">
        <span>Link</span>
        <svg aria-hidden="true" class="cta-btn__icon" focusable="false" height="8" width="8">
            <use xlink:href="#icon-arrow-right-bold"></use>
        </svg>
    </span>
</a>
        

@ebay/skin/card

A card forms the content layer in the eBay Design System topography of background layer, content layer & content. This system requires that the background layer (typically the HTML body tag) have zero margin and padding. The card content layer is responsible for creating all necessary margin & padding.

There are three types of card: regular card, primary card & full-page card.

All cards use a nested card__cell element to denote the inner content of the card block. Any content placed outside of this cell will be full-bleed (i.e. edge to edge). See hero card section below for more information.

NOTE: in all card examples below we use a fixed-height div to simulate Skin's default grey background layer.

Regular Card

Use the card class to create a card with vertical and horizontal margins.

This 'floating' effect helps differentiate data sets and is used to identify secondary, tertiary & extraneous content.

Title

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

<div class="card">
    <div class="card__cell">
        <h2>Title</h2>
        <h3>Heading</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
        <h3>Heading</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
    </div>
</div>
    

Primary Card

Use the card--primary modifier to create a primary, full-width card.

Only one primary card should be deployed per page. It is used to identify primary content and spans the entire width of the background layer.

Title

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

<div class="card card--primary">
    <div class="card__cell">
        <h2>Title</h2>
        <h3>Heading</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
        <h3>Heading</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
    </div>
</div>
    

Full Page Card

Applying the card class directly to the body tag creates a full page card. Full page cards span the full width and height of the page.

Title

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

<body class="card">
    <div class="card__cell">
        <h1>Title</h1>
        <div>
            <h2>Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
        </div>
        <div>
            <h2>Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
        </div>
    </div>
</div>
    

Hero Card

For cards with large hero headers, apply the card--hero modifier. The hero element must immediately precede the card__cell element.

TIP: A CSS background image can also be used as the hero image.

Title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

Title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.

<div class="card card--primary card--hero">
    <img alt="" class="responsive-image" src="http://i.ebayimg.com/00/s/OTI0WDE1MzY=/z/H4gAAOSwJQdXBsto/$_57.JPG?set_id=80000000000" />
    <div class="card__cell">
        <h2>Title</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
    </div>
</div>
<div class="card">
    <div class="card__cell">
        <h2>Title</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus convallis molestie erat, ut adipiscing risus blandit vel. Vivamus luctus elementum lorem, eu sodales velit sagittis id. Donec a est ligula, eget volutpat augue.</p>
    </div>
</div>
    

Dialog Cards

Cards can also be used inside of any dialog.

<div role="dialog" class="dialog" id="dialog-card" aria-labelledby="dialog-card-title" hidden>
    <div class="dialog__window" role="document">
        <header class="dialog__header">
            <h2 class="dialog__title" id="dialog-card-title">Dialog with Cards</h2>
            <button class="dialog__close" aria-label="Close dialog" type="button">
                <svg aria-hidden="true" focusable="false">
                    <use xlink:href="#icon-close"></use>
                </svg>
            </button>
        </header>
        <div class="dialog__body">
            <div class="card card--primary">
                <div class="card__cell">
                    <!-- card content -->
                </div>
            </div>
            <div class="card">
                <div class="card__cell">
                    <!-- card content -->
            </div>
        </div>
    </div>
    <div class="dialog__mask"></div>
</div>
    

To create a full content layer inside of a dialog, apply the dialog--card modifier to the dialog block.

@ebay/skin/checkbox

A checkbox is a form control that allows the user to toggle a choice on or off.

The purpose of a checkbox is to collect form data; therefore a checkbox should always be used in conjunction with a form, label and submit button.

Default Checkbox

Use the checkbox base class to create a checkbox.

The checkbox is decoupled from it's text label to allow more flexibility in terms of layout. How and where you provide this label is up to you, but do not forget it!

<span class="checkbox">
    <input class="checkbox__control" type="checkbox" name="checkbox-default" />
    <span class="checkbox__icon"></span>
</span>
    

The default checkbox leverages background SVG, but foreground SVG is also supported.

<span class="checkbox">
    <input aria-label="SVG checkbox example" class="checkbox__control" type="checkbox" />
    <span class="checkbox__icon" hidden>
        <svg class="checkbox__unchecked" focusable="false" height="18" width="18">
            <use xlink:href="#icon-checkbox-unchecked"></use>
        </svg>
        <svg class="checkbox__checked" focusable="false" height="18" width="18">
            <use xlink:href="#icon-checkbox-checked"></use>
        </svg>
    </span>
</span>
    

Disabled Checkbox

Use the disabled attribute to disable any checkbox input.

<span class="checkbox">
    <input class="checkbox__control" type="checkbox" name="checkbox-disabled" checked disabled  />
    <span class="checkbox__icon"></span>
</span>
    

Grouped Checkboxes

A group of checkboxes allows multi-select (unlike a group of radio buttons which enforces single-select).

A fieldset and legend are required in order to create the correct grouping semantics. Note that the Skin global module removes the default fieldset border and padding.

TIP: To stack checkboxes vertically instead of side-by-side, simply replace the span wrapper with a div wrapper.

Choose an Option
<fieldset>
    <legend>Choose an Option</legend>
    <span class="field">
        <span class="checkbox field__control">
            <input class="checkbox__control" id="group-checkbox-1" type="checkbox" value="1" name="checkbox-group" />
            <span class="checkbox__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-checkbox-1">Option 1</label>
    </span>
    <span class="field">
        <span class="checkbox field__control">
            <input class="checkbox__control" id="group-checkbox-2" type="checkbox" value="2" name="checkbox-group" />
            <span class="checkbox__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-checkbox-2">Option 2</label>
    </span>
    <span class="field">
        <span class="checkbox field__control">
            <input class="checkbox__control" id="group-checkbox-3" type="checkbox" value="3" name="checkbox-group" />
            <span class="checkbox__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-checkbox-3">Option 3</label>
    </span>
</fieldset>
    

Custom Checkbox

The default checkbox shown above uses an SVG background image, and therefore has a fixed colour. Foreground SVG, while slightly more verbose, honours the CSS cascade, thus allowing any possible colour for the checkbox icon.

<span class="checkbox">
    <input class="checkbox__control" type="checkbox" />
    <span class="checkbox__icon" hidden>
        <svg aria-hidden="true" class="checkbox__unchecked" focusable="false">
            <use xlink:href="#icon-checkbox-unchecked"></use>
        </svg>
        <svg aria-hidden="true" class="checkbox__checked" focusable="false" style="color: #5ba71b">
            <use xlink:href="#icon-checkbox-checked"></use>
        </svg>
    </span>
</span>
    

NOTE: The hidden property ensures that the SVG icon is not visible alongside the native icon when the page is in a non-CSS state. The hidden state will be overriden by CSS. We consider this an unobtrusive, progressive enhancement of the native HTML checkbox.

The checkbox module can use any inline SVG for it's checked and unchecked states.

<span class="checkbox">
    <input class="checkbox__control" type="checkbox" />
    <span class="checkbox__icon" hidden>
        <svg aria-hidden="true" class="checkbox__unchecked" focusable="false">
            <use xlink:href="#icon-checkbox-unchecked"></use>
        </svg>
        <svg aria-hidden="true" class="checkbox__checked" focusable="false" style="color: #5ba71b">
            <use xlink:href="#icon-confirmation"></use>
        </svg>
    </span>
</span>
    

Be careful when using a custom checkbox; the icon for each state must still give enough affordance to a user that it represents an interactive control.

@ebay/skin/color

Static sites that do not have access to the LESS variables can leverage the product palette via the color module class names.

  • color-text-default
  • color-text-secondary
  • color-information-background
  • color-warning-background
  • color-critical-text
  • color-critical-background
  • color-confirmation-text
  • color-confirmation-background

@ebay/skin/combobox

An enhanced textbox that allows free text input, or selection from a predefined list of values, or a combination of both. Hence the term 'combo'.

NOTE: Only limited JavaScript behaviour has been implemented in these combobox examples. For example, we do not demonstrate autocomplete functionality. For detailed behaviour requirements, please visit the eBay MIND Pattern for Combobox.

Default Combobox

By default, no option in the list should be selected.

Option 1
Option 2
Option 3
<span class="combobox">
    <span class="combobox__control">
        <input placeholder="Combobox" role="combobox" type="text" aria-haspopup="listbox" aria-owns="listbox1" />
        <span class="combobox__icon" aria-hidden="true"></span>
    </span>
    <div id="listbox1" class="combobox__options" role="listbox">
        <div class="combobox__option" role="option">
            <span>Option 1</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 2</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 3</span>
            <span class="combobox__status"></span>
        </div>
    </div>
</span>
        

The combobox overlay becomes automatically scrollable at a height of 400px.

Option 1
Option 2
Option 3
Option 4
Option 5
Option 6
Option 7
Option 8
Option 9
Option 10
Option 11
Option 12
Option 13
Option 14
Option 15
Option 16
Option 17
Option 18
Option 19
Option 20
Option 21
Option 22
Option 23
Option 24
Option 25
Option 26
Option 27
Option 28
Option 29
Option 30
Option 31
Option 32
Option 33
Option 34
Option 35
Option 36
Option 37
Option 38
Option 39
Option 40
Option 41
Option 42
Option 43
Option 44
Option 45
Option 46
Option 47
Option 48
Option 49
Option 50

Disabled Combobox

Apply the disabled property to disable the combobox.

Option 1
Option 2
Option 3
<span class="combobox">
    <span class="combobox__control">
        <input placeholder="Combobox" role="combobox" type="text" aria-haspopup="listbox" aria-owns="listbox2" disabled />
        <span class="combobox__icon" aria-hidden="true"></span>
    </span>
    <div id="listbox2" class="combobox__options" role="listbox">
        <div class="combobox__option" role="option">
            <span>Option 1</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 2</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 3</span>
            <span class="combobox__status"></span>
        </div>
    </div>
</span>
        

Readonly Combobox

A readonly combobox is intended for use as a custom implementation of the native HTML select element. Unfortunately, a readonly combobox exhibits some UX issues on iOS, which is why for now we recommend using the listbox instead.

Apply the readonly property to create a readonly combobox.

By default, the first item should be selected if the user does not specify a selection. This matches the behaviour of a native HTML select element.

Option 1
Option 2
Option 3
<span class="combobox">
    <span class="combobox__control">
        <input role="combobox" type="text" value="Option 1" aria-haspopup="listbox" aria-owns="listbox4" readonly />
        <span class="combobox__icon" aria-hidden="true"></span>
    </span>
    <div id="listbox4" class="combobox__options" role="listbox">
        <div class="combobox__option" role="option" aria-selected="true">
            <span>Option 1</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 2</span>
            <span class="combobox__status"></span>
        </div>
        <div class="combobox__option" role="option">
            <span>Option 3</span>
            <span class="combobox__status"></span>
        </div>
    </div>
</span>
        

@ebay/skin/dialog

A dialog is a child window spawned by the main web page or application. This window forms a new background layer in our design system topography.

A dialog must remain in a hidden state for all users and devices until called upon.

The first h2 tag will become the de facto title for the dialog. We suggest you place it at the beginning of the dialog__body. This will ensure it is semantically correct, and won't interfere with layout of the body content.

All dialogs require a visible close button.

Default Dialog

The default dialog is a lightbox.

The lightbox will have a margin of 15vh and automatically scales vertically.

<div role="dialog" aria-labelledby="dialog-title" class="dialog" hidden>
    <div class="dialog__window" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Fill Dialog

Apply the dialog__window--fill modifier to have the lightbox fill at least 70% of the screen (centered vertically).

<div role="dialog" aria-labelledby="dialog-title" class="dialog" hidden>
    <div class="dialog__window dialog__window--fill" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Left Panel Dialog

Apply the dialog__window--left modifier to have the dialog act as a left side panel (100vh height and aligned to the left side of the screen).

<div role="dialog" aria-labelledby="dialog-title" class="dialog" hidden>
    <div class="dialog__window dialog__window--left" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Right Panel Dialog

Apply the dialog__window--right modifier to have the dialog act as a right side panel (100vh height and aligned to the right side of the screen).

<div role="dialog" aria-labelledby="dialog-title" class="dialog" hidden>
    <div class="dialog__window dialog__window--right" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Fullscreen Panel Dialog

Apply the dialog__window--full modifier to have the dialog take up the entire viewport.

Having a mask on a fullscreen dialog doesn't typically make sense and can cause the animations to look a bit strange. You can disable the default background mask of the dialog by applying the dialog--no-mask modifier on the dialog element.

<div role="dialog" aria-labelledby="dialog-title" class="dialog dialog--no-mask" hidden>
    <div class="dialog__window dialog__window--full" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Scrolling Panel Dialog

When you have a lot of content, the dialog will automatically handle scrolling for your.

<div role="dialog" aria-labelledby="dialog-title" class="dialog dialog--no-mask" hidden>
    <div class="dialog__window dialog__window--full" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p>Lorem ... 1</p>
            <p>Lorem ... 2</p>
            <p>(you get the idea)</p>
            <p>Lorem ... n</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Dialog Transitions

Skin currently supports two types of dialog transition: fade and slide. Because CSS cannot transition an element to and from hidden (i.e. "display:none"), transitions are acheived using two classes applied during different stages of the animation. Before applying an animation class to the dialog component you must first apply the primer class which will be $name-init where $name is the base class. The dialog component has two different animation base classes dialog--show and dialog--hide.

Firstly the -init postfix must be applied to dialog component to prime animation. One animation frame later the -init postfix must be removed and the base class applied to start the animation. Finally once the animation has completed remove the base class.

An example implementation is shown below.

const dialogEl = document.querySelector(".dialog");
const windowEl = dialogEl.querySelector(".dialog__window");
const openBtnEl = document.querySelector("#dialog-open");
const closeBtnEl = dialogEl.querySelector(".dialog__close");

// Trigger dialog show animation.
openBtnEl.addEventListener("click", () => {
    dialogEl.classList.add("dialog--show-init");
    dialogEl.removeAttribute("hidden");

    requestAnimationFrame(() => requestAnimationFrame(() => {
        // Two RAFS to ensure this happens on the next animation frame.
        dialogEl.classList.remove("dialog--show-init");
        dialogEl.classList.add("dialog--show");

        windowEl.addEventListener("transitionend", () => {
            /**
             * The window animation is the longest, so we wait for it to
             * finish before removing the classes.
             */
            dialogEl.classList.remove("dialog--show");
        }, { once: true });
    }));
});

// Trigger dialog hide animation. (In the real world the dialog mask) should also be handled.
closeBtnEl.addEventListener("click", () => {
    dialogEl.classList.add("dialog--hide-init");
    dialogEl.setAttribute("hidden", "");

    requestAnimationFrame(() => requestAnimationFrame(() => {
        // Two RAFS to ensure this happens on the next animation frame.
        dialogEl.classList.remove("dialog--hide-init");
        dialogEl.classList.add("dialog--hide");

        windowEl.addEventListener("transitionend", () => {
            /**
             * The window animation is the longest, so we wait for it to
             * finish before removing the classes.
             */
            dialogEl.classList.remove("dialog--hide");
        }, { once: true });
    }));
});

    

Fade Transition

Any dialog window and mask can be faded in and out, using the dialog__window--fade modifier on the dialog__window and a dialog--mask-fade modifier on the dialog.

The default fade duration is 16ms.

<div role="dialog" aria-labelledby="dialog-title" class="dialog dialog--mask-fade" hidden>
    <div class="dialog__window dialog__window--fade" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p>
                <a href="http://www.ebay.com">www.ebay.com</a>
            </p>
        </div>
    </div>
</div>

<div role="dialog" aria-labelledby="dialog-title" class="dialog dialog--no-mask" hidden>
    <div class="dialog__window dialog__window--full dialog__window--fade" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

Slide Transition

Any panel or fullscreen dialog can slide in and out, using the dialog__window--slide modifier on the dialog__window.

The slide transition duration is 32ms. An accompanying dialog--mask-fade-slow modifier on the dialog should also be applied. This slower fade matches the 32ms of the slide transition.

<div role="dialog" aria-labelledby="dialog-title" class="dialog dialog--mask-fade-slow" hidden>
    <div class="dialog__window dialog__window--left dialog__window--slide" role="document">
        <button aria-label="Close dialog" class="dialog__close" type="button">
            <span></span>
        </button>
        <div class="dialog__body">
            <h2 id="dialog-title" class="large-text-1 bold-text">Heading</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
                magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p><a href="http://www.ebay.com">www.ebay.com</a></p>
        </div>
    </div>
</div>
        

@ebay/skin/field

The field module facilitates the layout of a form control and it's associated label, plus any other applicable text or sub-controls (e.g. error text or help button).

Unstacked Field

The field__label & field__control elements are inline by default, taking up only as much horizontal space as they need.

Multiple fields can be laid out inline by using the span tag with field class, as per the example below.

<span class="field">
    <label class="field__label" for="field1">Field 1</label>
    <span class="field__control textbox">
        <input class="textbox__control" id="field1" type="text" placeholder="placeholder text" />
    </span>
</span>
<span class="field">
    <label class="field__label" for="field2">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select name="field2" id="field2">
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
<span class="field">
    <label class="field__label" for="field3">Field 3</label>
    <span class="field__control switch">
        <input aria-label="Switch Demo" class="switch__control" role="switch" type="checkbox" id="field3" />
        <span class="switch__button"></span>
    </span>
</span>
    

Replace the span tag with a div tag to layout fields in blocks, as per the following example.

Stacked Field

For a label stacked above the control, use the field__label--stacked element modifier.

Again, multiple fields can be laid out inline by using a span tag, as per the example below.

<span class="field">
    <label class="field__label field__label--stacked" for="field1">Field 1</label>
    <span class="textbox">
        <input class="textbox__control" id="field1" type="text" placeholder="placeholder text" />
    </span>
</span>
<span class="field">
    <label class="field__label field__label--stacked" for="field2">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select name="field2" id="field2">
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
<span class="field">
    <label class="field__label field__label--stacked">Field 3</label>
    <span class="field__control switch">
        <input aria-label="Switch Demo" class="switch__control" role="switch" type="checkbox" id="field3" />
        <span class="switch__button"></span>
    </span>
</span>
    

Replace the span tag with a div tag to layout the stacked fields in blocks, as per the example below.

Field Font-Size

The field label will honour any font-size cascade (so be careful if this is not your intention!).

Notice that form controls do not inherit the cascade. This is default browser behaviour.

<span class="field" style="font-size: 18px;">
    <label class="field__label" for="email">Field 1</label>
    <span class="field__control textbox textbox--large">
        <input class="textbox__control" id="field1" type="text" placeholder="placeholder text" />
    </span>
</span>
<span class="field" style="font-size: 18px;">
    <label class="field__label" for="size">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select name="size" id="size">
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
<span class="field" style="font-size: 18px;">
    <label class="field__label" for="field3">Field 3</label>
    <span class="field__control switch">
        <input aria-label="Switch Demo" class="switch__control" role="switch" type="checkbox" id="field3" />
        <span class="switch__button"></span>
    </span>
</span>
    

Disabled Field

The disabled control is conveyed using the disabled attribute. The value of a disabled control is not passed to the server.

<span class="field">
    <label class="field__label" for="email">Field 1</label>
    <span class="field__control textbox">
        <input class="textbox__control" id="field1" type="text" value="placeholder text" disabled />
    </span>
</span>
<span class="field">
    <label class="field__label" for="size">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select name="field2" id="field2" disabled>
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
<span class="field">
    <label class="field__label" for="field3">Field 3</label>
    <span class="field__control switch">
        <input disabled aria-label="Switch Demo" class="switch__control" role="switch" type="checkbox" id="field3" />
        <span class="switch__button"></span>
    </span>
</span>
    

TIP: Disabled controls are exempt from WCAG colour contrast requirements.

Readonly Field

A readonly control is conveyed using the readonly attribute. The value of a readonly control is passed to the server.

<span class="field">
    <label class="field__label" for="email">Field 1</label>
    <span class="field__control textbox">
        <input class="textbox__control" id="field1" type="text" value="placeholder text" readonly />
    </span>
</span>
<span class="field">
    <label class="field__label" for="size">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select name="field2" id="field2" readonly>
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
    

Required Field

A required field is conveyed visually with an asterisk, and non-visually using the aria-required property.

<span class="field">
    <label class="field__label" for="email">Field 1 <sup>*</sup></label>
    <span class="field__control textbox">
        <input aria-required="true" class="textbox__control" id="field1" type="text" placeholder="placeholder text">
    </span>
</div>
<span class="field">
    <label class="field__label" for="size">Field 2 <sup>*</sup></label>
    <span class="field__control">
        <span class="select">
            <select aria-required="true" id="field2">
                <option value="0" disabled selected>-select-</option>
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
    

Invalid Field

An invalid control is conveyed visually via a combination of red outline and some other indicator (usually either text and/or an icon). The invalid state is conveyed non-visually using the aria-invalid state.

IMPORTANT: The example below shows the field with red border only. Do not forget that colour should not be used as the only visual means of conveying information. A description and/or icon is also required. See next section for more details.

<span class="field">
    <label class="field__label" for="email">Field 1</label>
    <span class="field__control textbox">
        <input aria-invalid="true" class="textbox__control" id="field1" type="text" placeholder="placeholder text">
    </span>
</span>
<span class="field">
    <label class="field__label" for="size">Field 2</label>
    <span class="field__control">
        <span class="select">
            <select aria-invalid="true" id="field2">
                <option value="0" disabled selected>-select-</option>
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
            <span class="select__icon"></span>
        </span>
    </span>
</span>
    

Field Description

A field may have nearby text to describe additional instructions, status or validation error of the control.

The field__description element defines some minimal styling, but does not dictate location or layout. This element has modifiers for confirmation, information and attention, depending on the type of descriptive text (or icon).

TIP: The description element can be designated as an ARIA live-region if client-side updates occur.

Text on Side of Field

A description can be placed adjacent to any stacked or unstacked field simply by using an inline-level tag, such as span.

Field description or error
<span class="field">
    <label class="field__label" for="field1">Field Label</label>
    <span class="field__control textbox">
        <input aria-describedby="field1-description" class="textbox__control" id="field1" type="text" />
    </span>
    <span class="field__description" id="field1-description">
        <span>Field description or error</span>
    </span>
</span>
    

Text Below Stacked Field

A description can be placed underneath a stacked field simply by using a block-level tag, such as div.

Field description or error
<span class="field">
    <label class="field__label field__label--stacked" for="field1">Field Label</label>
    <div class="field__control textbox">
        <input aria-describedby="field1-description" class="textbox__control" id="field1" type="text" />
    </div>
    <div class="field__description" id="field1-description">
        <span>Field description or error</span>
    </div>
</span>
    

Text Above or Below Unstacked Field

A description can be added directly above and/or below the control by utlising CSS table-layout via the field--table modifier and field__row elements.

Field description or error
<span class="field field--table">
    <div class="field__row">
        <span><!-- empty cell--></span>
        <span class="field__description" id="field1-description">
            <span>Field description or error</span>
        </span>
    </div>
    <div class="field__row">
        <label class="field__label" for="field1">Field Label</label>
        <span class="textbox">
            <input aria-describedby="field1-description" class="textbox__control" id="field1" type="text" />
        </span>
    </div>
</span>
    

Fluid Field

Form control elements (such as select and input) are inline-block by default, and will only use up as much of their parent's horizontal space as they need.

For a stacked field the control must be set to 100% width (using the fluid utility class) to fill all available space.

<div class="field-group">
    <span class="field fluid">
        <label class="field__label field__label--stacked" for="field1">Field 1</label>
        <div class="field__control textbox">
            <input class="textbox__control fluid" id="field1" type="text" placeholder="placeholder text" />
        </div>
    </span>
    <span class="field fluid">
        <label class="field__label field__label--stacked" for="field2">Field 2</label>
        <div class="field__control fluid">
            <div class="select select--fluid">
                <select name="field2" id="field2">
                    <option value="1">Option 1</option>
                    <option value="2">Option 2</option>
                    <option value="3">Option 3</option>
                </select>
                <span class="select__icon"></span>
            </div>
        </div>
    </span>
</div>
    

The above example shows the fields in a flexbox layout. This layout is created using the field-group helper class. Notice that each field is also set to fluid, in order to fill all available flexbox space (flexbox layout takes care of dividing the space evenly between fluid fields).

If we set the form control width to 100% in an unstacked field, the control would flow to a new line below the label (effectively behaving like a stacked label). This behaviour can be avoided by adding an additional field__group element to create flex layout inside of the field.

<div class="field-group">
    <span class="field fluid">
        <span class="field__group fluid">
            <label class="field__label no-wrap" for="field1">Field 1</label>
            <span class="field__control fluid textbox">
                <input class="textbox__control fluid" id="field1" type="text" placeholder="placeholder text" />
            </span>
        </span>
    </span>
    <span class="field fluid">
        <span class="field__group fluid">
            <label class="field__label no-wrap" for="field2">Field 2</label>
            <span class="field__control fluid">
                <span class="select select--fluid">
                    <select name="field2" id="field2">
                        <option value="1">Option 1</option>
                        <option value="2">Option 2</option>
                        <option value="3">Option 3</option>
                    </select>
                    <span class="select__icon"></span>
                </span>
            </span>
        </span>
    </span>
</div>
    

TIP: You may want to experiment with sizes other than 100%, and also the flexbox justify-content property.

For a fluid control and description, those elements can be wrapped in a field__group container to create flex layout.

Field description or error
Field description or error
<div class="field-group">
    <span class="field fluid">
        <label class="field__label field__label--stacked" for="field-fluid-block-1">Field 1</label>
        <div class="field__group">
            <span class="field__control textbox fluid">
                <input class="textbox__control fluid" id="field-fluid-block-1" type="text" placeholder="placeholder text" />
            </span>
            <span class="field__description">
                <span>Field description or error</span>
            </span>
        </div>
    </span>
    <span class="field fluid">
        <label class="field__label field__label--stacked" for="field-fluid-block-2">Field 2</label>
        <div class="field__group">
            <div class="field__control fluid">
                <div class="select select--fluid">
                    <select name="field-fluid-block-2" id="field-fluid-block-2">
                        <option value="1">Option 1</option>
                        <option value="2">Option 2</option>
                        <option value="3">Option 3</option>
                    </select>
                    <span class="select__icon"></span>
                </div>
            </div>
            <span class="field__description">
                <span>Field description or error</span>
            </span>
        </div>
    </span>
</div>
        

@ebay/skin/global

Global creates a unique look for the eBay brand by defining the style of common elements such as headings, paragraphs, fieldsets, images and links.

Global is included with the core bundle.

Font Family

Applications on Node.js stack will not receive the eBay Market Sans font as the default font. Applications must use the ebay-font loader.

Websites utilising Skin via CDN will have the eBay Market Sans font as the default font.

Paragraph without Market Sans

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Paragraph with Market Sans

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Link States

The states below are hardcoded for the purpose of this demo.

@ebay/skin/icon

The icon module provides full access to the eBay iconography via the <svg> tag (i.e. foreground icons) and the <span> tag (i.e. background icons).

By default, the icon module bundles all CSS for both types of tag. However, the background icon CSS contains a base64 data-url for every icon in the set, therefore significantly increasing CSS payload. For this reason, Skin also provides the ability to bring in background or foreground CSS independently, via their own modules.

Below we give a quick, introductory example of how to use each type of icon; followed up by the full list of icons.

@ebay/skin/icon/foreground

Foregound icons (the <svg> tag) can inherit their colour via the CSS cascade.

To avoid gigantic icons when in a non-CSS state, we use the SVG width and height attributes to override the browser's default 300x150 size.

@ebay/skin/icon/background

Background icons (the <span> tag) have their colour fixed in base64 and cannot be changed via CSS.

Remember, this module contains a base64 encoded string for every icon in the set, therefore a significant increase in CSS payload will occur.

<svg class="icon icon--info" focusable="false" height="19" width="21">
    <use xlink:href="#icon-info"></use>
</svg>
        
<span class="icon icon--info"></span>
        

NOTE: Skin removes all mouse and touch events on foreground icons due to a bug in IE. To add events to these icons you should wrap them in another element and attach your events there.

Icon Accessibility

An icon can be presentational or non-presentational.

Presentational Icons

A presentational icon provides no additional content, context or affordance to a page, section or widget.

Presentational foreground icons require aria-hidden="true".

Presentational background icons require no special treatment. Assistive technology simply ignores empty span tags.

Non-Presentational Icons

A non-presentational icon provides essential content, context or affordance to a page, section or widget.

Non-presentational icons nested inside of an interactive element (typically a button or link) require no special treatment. The label and role of the interactive element is sufficient for assistive technology.

Non-presentational icons not nested inside of an interactive element require role="img" and an aria-label.

Filter Icons

filter-gallery
filter-single
filter-list

Form Icons

checkbox-unchecked
checkbox-checked
radio-unchecked
radio-checked
tick

Carousel Icons

pause
play

Notice Icons

confirmation
information
attention

Arrow Icons

arrow-down
arrow-up

Chevron Icons

chevron-up
chevron-down
chevron-left
chevron-right
chevron-light-left
chevron-light-right

Navigation Icons

menu
close
cart
notification
search

Navigation Support Icons

download
help
info
messages
messages-open
profile
selling
settings
add
window

Search Icons

camera
clear

Misc Icons

alert
clock
minus
star
trash
autocomplete
box
call
chat
comments
fire
magnify
sort
success
tag

Feedback Icons

feedback-neutral
feedback-negative
feedback-positive

Null Icons

cart-null
caution-null
collections-null
glasses-null
notifications-null
pencil-null
pictures-null
selling-null
shopping-null

Editing Icons

bold
bulleted-list
center-aligned
center-justified
italic
justified
left-aligned
left-justified
link
numbered-list
right-aligned
right-justified
strike-thru
underline

Selling Icons

auction
best-offer
checkout-complete
classified-ad
fixed-price
item-feedback
item-paid
item-shipped
part-paid
payment-refunded
relisted
requested-total
second-chance
seller-feedback

@ebay/skin/label

The label module consists of a "floating label" for textbox. Floating labels appear to sit inside the textbox when it has no value or focus, and sit above the textbox otherwise.

Floating Label with no Value

If the textbox has no value, the label can be positioned inside the textbox.

<span class="floating-label">
    <label class="floating-label__label" for="firstName">First Name</label>
    <span class="textbox">
        <input class="textbox__control textbox__control--underline" id="firstName" type="text" />
    </span>
</span>
    

Floating Label with Value

If the textbox has a value, the label must be positioned above the textbox.

<span class="floating-label">
    <label class="floating-label__label" for="lastName">Last Name</label>
    <span class="textbox">
        <input class="textbox__control textbox__control--underline" id="lastName" type="text" value="Smith" />
    </span>
</span>
    

Floating Label with Placeholder

The placeholder always remains obscured until the textbox gains focus.

<span class="floating-label">
    <label class="floating-label__label" for="dob">Date Of Birth</label>
    <span class="textbox">
        <input class="textbox__control textbox__control--underline" id="dob" type="text" placeholder="MM/DD/YYYY" />
    </span>
</span>
    

Floating Label with Disabled Textbox

Use the disabled property & floating-label__label--disabled modifier on the input element and the label element respectively to disable the input.

<span class="floating-label">
    <label class="floating-label__label floating-label__label--disabled" for="firstName">First Name</label>
    <span class="textbox">
        <input class="textbox__control textbox__control--underline" id="firstName02" type="text" disabled />
    </span>
</span>
    

Floating Label with Invalid Textbox

Set the aria-invalid property to true to semantically and visually highlight the invalid state.

<span class="floating-label">
    <label class="floating-label__label" for="firstName">First Name</label>
    <span class="textbox">
        <input class="textbox__control textbox__control--underline" id="firstName03" type="text" aria-invalid="true" />
    </span>
</span>
    

Floating Label Transitions

By default, with only the base markup shown above, the label remains in a floating state above the input. This default state ensures that the label does not obscure the textbox value while we wait for JavaScript.

When JavaScript is ready, the label can be re-positioned inside the textbox by adding the floating-label__label--inline modifier class. By default, this re-positioning of label happens instantly, without a transition. Typically, we do not want to show transitions on the initial page render, as this might be too jarring and distracting for some users.

To opt into transitions after the initial render is complete, add the floating-label__label--animate modifier when the textbox receives focus.

The examples above use makeup-floating-label, a simple JavaScript module that adds the aforementioned logic. Feel free to use this module or use it as the basis to roll your own.

@ebay/skin/less

The Less module enables developers to access our public Less variables & mixins in their application.

Our Less module is not intended as a general-purpose library of utility mixins and variables such as LessHat..

{
    "dependencies": {
      "lasso": "^3",
      "lasso-less": "^3",
      "@ebay/skin": "^7"
    }
}
    

NOTE: This module requires the additional lasso-less plugin dependency in your app package.json:

Icon Mixins

The Less module allows access to individual icons in our iconography via mixins.

Typography Mixins

  • .ds4-typography-giant-2
  • .ds4-typography-giant-1
  • .ds4-typography-large-2-bold
  • .ds4-typography-large-2
  • .ds4-typography-large-2-secondary
  • .ds4-typography-large-1-bold
  • .ds4-typography-large-1
  • .ds4-typography-large-1-secondary
  • .ds4-typography-medium-bold
  • .ds4-typography-medium
  • .ds4-typography-medium-secondary
  • .ds4-typography-regular-bold
  • .ds4-typography-regular
  • .ds4-typography-regular-secondary
  • .ds4-typography-small-bold
  • .ds4-typography-small
  • .ds4-typography-small-secondary

Core Color Variables

@ds4-color-core-gray-jet;
@ds4-color-core-gray-davys;
@ds4-color-core-gray-dim;
@ds4-color-core-gray-spanish;
@ds4-color-core-gray-silver;
@ds4-color-core-gray-gainsboro;
@ds4-color-core-gray-light;
@ds4-color-core-orange;
@ds4-color-core-red;
@ds4-color-core-purple;
@ds4-color-core-blue-dark;
@ds4-color-core-blue;
@ds4-color-core-violet;
@ds4-color-core-green;
@ds4-color-core-beige;
@ds4-color-core-beige-light;

Text Color Variables

@color-text-default;
@color-text-subheader;
@color-text-footnote;
@color-text-disabled;
@color-text-critical;
@color-text-positive;

Interface Color Variables

@color-interface-hot;
@color-interface-cta-dark;
@color-interface-cta;
@color-interface-cta-light;
@color-interface-positive;
@color-interface-line-separator;
@color-interface-view-background;
@color-interface-base;
@color-interface-base-light;
@color-interface-modal-shadow;
@color-interface-menu-shadow;
@color-interface-card-visited;
@color-interface-card-background;
@color-interface-card-selection;
@color-interface-card-highlight;
@color-interface-inline-text-edit;

Infographic Color Variables

@color-infographic-red-lightest;
@color-infographic-red-light;
@color-infographic-red;
@color-infographic-red-interaction;
@color-infographic-green-lightest;
@color-infographic-green-light;
@color-infographic-green;
@color-infographic-green-interaction;
@color-infographic-blue-lightest;
@color-infographic-blue-light;
@color-infographic-blue;
@color-infographic-blue-interaction;
@color-infographic-orange-lightest;
@color-infographic-orange-light;
@color-infographic-orange;
@color-infographic-orange-interaction;
@color-infographic-purple-lightest;
@color-infographic-purple-light;
@color-infographic-purple;
@color-infographic-purple-interaction;
@color-infographic-gray-lightest;
@color-infographic-gray-light;
@color-infographic-gray;
@color-infographic-gray-interaction;

@ebay/skin/listbox

A listbox is intended for use as a custom implementation of the native HTML select element.

Because the listbox pattern uses a button element, it's value will not be submitted along with other form data without the assistance of JavaScript.

NOTE: only limited JavaScript behaviour has been implemented in these listbox examples. For detailed behaviour requirements, please visit the W3C's Collapsible Dropdown Listbox Example.

Default

By default, the first option should be selected if the user does not specify a selection. This matches the behaviour of a native HTML select element.

Option 1
Option 2
Option 3
<span class="listbox">
    <button class="expand-btn expand-btn--regular" aria-expanded="false" aria-haspopup="listbox">
        <span class="expand-btn__cell">
            <span>Option 1</span>
            <span class="expand-btn__icon"></span>
        </span>
    </button>
    <div class="listbox__options" role="listbox" tabindex="-1">
        <div class="listbox__option" role="option">
            <span>Option 1</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option">
            <span>Option 2</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option">
            <span>Option 3</span>
            <span class="listbox__status"></span>
        </div>
    </div>
</span>
        

Selected State

An initial selection can be specified by applying the aria-selected state to a single option.

Option 1
Option 2
Option 3
<span class="listbox">
    <button class="expand-btn expand-btn--regular" aria-expanded="false" aria-haspopup="listbox">
        <span class="expand-btn__cell">
            <span>Option 1</span>
            <span class="expand-btn__icon"></span>
        </span>
    </button>
    <div class="listbox__options" role="listbox" tabindex="-1">
        <div class="listbox__option" role="option">
            <span>Option 1</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option" aria-selected="true">
            <span>Option 2</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option">
            <span>Option 3</span>
            <span class="listbox__status"></span>
        </div>
    </div>
</span>
        

Borderless

Apply the expand-btn--borderless modifier to create a borderless listbox.

Option 1
Option 2
Option 3
<span class="listbox">
    <button class="expand-btn expand-btn--regular" aria-expanded="false" aria-haspopup="listbox">
        <span class="expand-btn__cell">
            <span>Listbox</span>
            <span class="expand-btn__icon"></span>
        </span>
    </button>
    <div class="listbox__options" role="listbox" tabindex="-1">
        <div class="listbox__option" role="option">
            <span>Option 1</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option">
            <span>Option 2</span>
            <span class="listbox__status"></span>
        </div>
        <div class="listbox__option" role="option">
            <span>Option 3</span>
            <span class="listbox__status"></span>
        </div>
    </div>
</span>
        

@ebay/skin/marketsans

Market Sans is an exclusive typeface developed specifically for eBay. This module downloads and installs the typeface directly from the eBay CDN servers. The typeface can then be referenced via the 'Market Sans' font-family name.

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
<style>
    p {
        font-family:  'Market Sans', 'Helvetica Neue', Helvetica, Arial, Roboto, sans-serif;
    }
</style>
    

TIP: The Market Sans font-family, and all fallbacks, can also be applied using the Less variable @font-family-market-sans.

@ebay/skin/notice

The purpose of a notice is to convey the next course of action for a task or flow. The notice must be clear and concise, with minimum cognitive load.

A notice may appear at page-level or inline-level, with a status of attention, confirmation, or information.

Page Notice

A page-level notice typically appears prominently at the top of the page or directly above a module. To aid discoverabilty of such important content for assistive technology, we make each page notice a landmark region with heading.

Congrats! You just listed "Spam and Eggs From the Cow's Perspective (paperback)."

Error. Please take another look at the following:
Card number, Expiration date & Security code.

Good news! You get free shipping on your next pair of shoes! Learn more.

<section aria-labelledby="confirmation-status" class="page-notice page-notice--confirmation">
    <h2 class="page-notice__status" id="confirmation-status">
        <span aria-label="Confirmation" role="img"></span>
    </h2>
    <div class="page-notice__content">
        <p><strong>Congrats!</strong> You just listed <a href="#">"Spam and Eggs From the Cow's Perspective</a> (paperback)."</p>
    </div>
</section>

<section aria-labelledby="attention-status" class="page-notice page-notice--attention">
    <h2 class="page-notice__status" id="attention-status">
        <span aria-label="Attention" role="img"></span>
    </h2>
    <div class="page-notice__content">
        <p><strong>Error.</strong> Please take another look at the following:<br /><a href="#">Card number</a>, <a href="#">Expiration date</a> &amp; <a href="#">Security code</a>.</p>
    </div>
</section>

<section aria-labelledby="information-status" class="page-notice page-notice--information" role="region">
    <h2 class="page-notice__status" id="information-status">
        <span aria-label="Information" role="img"></span>
    </h2>
    <div class="page-notice__content">
        <p><strong>Good news!</strong> You get free shipping on your next pair of shoes! <a href="#">Learn more</a>.</p>
    </div>
</section>
    

Dismissable Page Notice

Append a button with class page-notice__close to create a dismissable page notice.

Congrats! You just listed "Spam and Eggs From the Cow's Perspective (paperback)."

You can check your listing or sell another item

Good news! You get free shipping on your next pair of shoes! Learn more.

<section aria-labelledby="confirmation-status" class="page-notice page-notice--confirmation">
    <h2 class="page-notice__status" id="confirmation-status">
        <span aria-label="Confirmation" role="img"></span>
    </h2>
    <div class="page-notice__content">
        <p><strong>Congrats!</strong> You just listed <a href="#">"Spam and Eggs From the Cow's Perspective</a> (paperback)."</p>
        <p>You can check <a href="#">your listing</a> or <a href="#">sell another item</a></p>
    </div>
    <button aria-label="Dismiss notice" class="page-notice__close">
        <span role="img" aria-hidden="true"></span>
    </button>
</section>

<section aria-labelledby="information-status" class="page-notice page-notice--information" role="region">
    <h2 class="page-notice__status" id="information-status">
        <span aria-label="Information" role="img"></span>
    </h2>
    <div class="page-notice__content">
        <p><strong>Good news!</strong> You get free shipping on your next pair of shoes! <a href="#">Learn more</a>.</p>
    </div>
    <button aria-label="Dismiss notice" class="page-notice__close">
        <span role="img" aria-hidden="true"></span>
    </button>
</section>
     

Call-to-Action Page Notice

Use an anchor or button tag to create a 'call-to-action' page notice tile.

IMPORTANT: A call-to-action can only have one action, i.e. a link or button tag cannot contain any nested links or buttons.

 <span aria-labelledby="confirmation-status" role="region">
     <a href="http://www.ebay.com" class="page-notice page-notice--confirmation page-notice--fluid">
         <h2 class="page-notice__status">
             <span aria-label="Confirmation notice" id="confirmation-status" role="img"></span>
         </h2>
         <span class="page-notice__content page-notice__content--align-middle">
             <p>Congrats! You are the highest bidder!</p>
         </span>
         <span class="page-notice__cta" role="img" aria-hidden="true"></span>
     </a>
 </span>
     

Inline Notice

An inline-level notice is typically located near a form field or user interface control.

Delivered on May 1, 2017

Tracking number: 93878473859376898908657567

Update your credit card.

Global Shipping Program transaction.

<div class="inline-notice inline-notice--confirmation">
    <span class="inline-notice__status">
        <span aria-label="Confirmation" role="img"></span>
    </span>
    <span class="inline-notice__content">
        <p>Delivered on May 1, 2017</p>
        <p>Tracking number: <a href="#">93878473859376898908657567</a></p>
    </span>
</div>

<div class="inline-notice inline-notice--attention">
    <span class="inline-notice__status">
        <span aria-label="Attention" role="img"></span>
    </span>
    <span class="inline-notice__content">
        <p>Update your credit card.</p>
    </span>
</div>

<div class="inline-notice inline-notice--information">
    <span class="inline-notice__status">
        <span aria-label="Information" role="img"></span>
    </span>
    <span class="inline-notice__content">
        <p>Global Shipping Program transaction.</p>
    </span>
</div>
    

Flyout Notice DEPRECATED

A flyout-level notice is a flyout that points to a specific section or element of the page.

The DOM order of the element in the page is very important! To avoid keyboard and screen reader accessibility issues, the flyout notice should immediately follow the element that it points to.

Flyout notices are absolutely positioned by default. The notice will be positioned relatively to the nearest ancestor with relative positioning.

WARNING: Flyout notice has been deprecated in favour of the tooltip pattern.

Congrats! You are currently the high bidder, but you are close to getting outbid.

We had trouble connecting to PayPal. Please make your payment later.

We could not find any items that match your search. Try expanding your search to find more items.

Use fewer refinements.

<div class="flyout-notice flyout-notice--confirmation">
    <span class="flyout-notice__pointer flyout-notice__pointer--bottom-left"></span>
    <div class="flyout-notice__mask">
        <div class="flyout-notice__cell">
            <div class="flyout-notice__content">
                <p>Congrats! You are currently the high bidder, but you are close to getting outbid.</p>
            </div>
            <button class="flyout-notice__close" type="button" aria-label="Dismiss notice" >
                <span aria-hidden="true" role="img"></span>
            </button>
        </div>
    </div>
</div>
<div class="flyout-notice flyout-notice--attention">
    <span class="flyout-notice__pointer flyout-notice__pointer--top-left"></span>
    <div class="flyout-notice__mask">
        <div class="flyout-notice__cell">
            <div class="flyout-notice__content">
                <p>We had trouble connecting to PayPal. Please make your payment later.</p>
            </div>
            <button class="flyout-notice__close" type="button" aria-label="Dismiss notice">
                <span aria-hidden="true" role="img"></span>
            </button>
        </div>
    </div>
</div>
<div class="flyout-notice flyout-notice--information">
    <span class="flyout-notice__pointer flyout-notice__pointer--right"></span>
    <div class="flyout-notice__mask">
        <div class="flyout-notice__cell">
            <div class="flyout-notice__content">
                <p>We could not find any items that match your search. Try expanding your search to find more items.</p>
                <p><a href="http://www.ebay.com">Use fewer refinements.</a></p>
            </div>
            <button class="flyout-notice__close" type="button" aria-label="Dismiss notice" >
                <span aria-hidden="true" role="img"></span>
            </button>
        </div>
    </div>
</div>

@ebay/skin/radio

A radio button is a form control that allows a user to select a single option from a group of choices.

The purpose of a radio button is to collect form data. Therefore, radio buttons should always be used in conjunction with a form, label and submit button.

Default Radio

Use the radio base class to create a styled radio.

The radio is decoupled from it's text label to allow more flexibility in terms of layout. How and where you provide this label is up to you, but do not forget it!

<span class="radio">
    <input class="radio__control" type="radio" />
    <span class="radio__icon"></span>
</span>
    

The default radio leverages background SVG, but foreground SVG is also supported.

<span class="radio">
    <input aria-label="SVG radio example" class="radio__control" type="radio" />
    <span class="radio__icon" hidden>
        <svg class="radio__unchecked" focusable="false" height="18" width="18">
            <use xlink:href="#icon-radio-unchecked"></use>
        </svg>
        <svg class="radio__checked" focusable="false" height="18" width="18">
            <use xlink:href="#icon-radio-checked"></use>
        </svg>
    </span>
</span>
    

Disabled Radio

Use the disabled attribute to disable any radio input.

<span class="radio">
    <input class="radio__control" type="radio" checked disabled />
    <span class="radio__icon"></span>
</span>
    

Grouped Radio

A group of radios enforces single-select (unlike a group of checkboxes which allows multi-select).

A fieldset and legend are required in order to create the correct grouping semantics. Note that the Skin global module removes the default fieldset border and padding.

TIP: To stack radio buttons vertically instead of side-by-side, simply replace the span wrapper with a div wrapper.

Choose an Option
<fieldset>
    <legend>Choose an Option</legend>
    <span class="field">
        <span class="field__control radio">
            <input class="radio__control" id="group-radio-1" type="radio" value="1" name="radio-group" />
            <span class="radio__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-radio-1">Option 1</label>
    </span>
    <span class="field">
        <span class="field__control radio">
            <input class="radio__control" id="group-radio-2" type="radio" value="2" name="radio-group" />
            <span class="radio__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-radio-2">Option 2</label>
    </span>
    <span class="field">
        <span class="field__control radio">
            <input class="radio__control" id="group-radio-3" type="radio" value="3" name="radio-group" />
            <span class="radio__icon"></span>
        </span>
        <label class="field__label field__label--end" for="group-radio-3">Option 3</label>
    </span>
</fieldset>
    

Custom Radio

The default radio shown above uses an SVG background image, and therefore has a fixed colour. Foreground SVG, while slightly more verbose, honours the CSS cascade, thus allowing any possible colour for the radio icon.

<span class="radio">
    <input class="radio__control" type="radio" />
    <span class="radio__icon" hidden>
        <svg aria-hidden="true" class="radio__unchecked" focusable="false">
            <use xlink:href="#icon-radio-unchecked"></use>
        </svg>
        <svg aria-hidden="true" class="radio__checked" focusable="false" style="color: #5ba71b">
            <use xlink:href="#icon-radio-checked"></use>
        </svg>
    </span>
</span>
    

NOTE: The hidden property ensures that the SVG icon is not visible alongside the native icon when the page is in a non-CSS state. The hidden state will be overriden by CSS. We consider this an unobtrusive, progressive enhancement of the native HTML radio.

The radio module can use any inline SVG for it's checked and unchecked states.

<span class="field__control radio">
    <input class="radio__control" id="custom-radio-1" type="radio" value="1" name="radio-custom" />
    <span class="radio__icon" hidden>
        <svg aria-hidden="true" class="radio__unchecked" focusable="false">
            <use xlink:href="#icon-radio-unchecked"></use>
        </svg>
        <svg aria-hidden="true" class="radio__checked" focusable="false" style="color: #5ba71b">
            <use xlink:href="#icon-radio-confirmation"></use>
        </svg>
    </span>
</span>
    

Be careful when using a custom radio; the icon for each state must still give enough affordance to a user that it represents an interactive control.

@ebay/skin/select

A select allows the user to select one item from a list of options. A select is exactly the same as a normal HTML select (because it is one), but Skin's version uses a wrapper to style it.

The purpose of a select is to collect form data; therefore a select should always be used in conjunction with a form, label and submit button. If you are not submitting form data, then a menu maybe a better choice.

IMPORTANT: The examples below show the select in isolation, without any label. Please see the field module for details on labeling controls. Remember: every select requires a label!

Default select

<span class="select">
    <select name="options">
        <option value="item1">Option 1</option>
        <option value="item2">Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Disabled select

<span class="select">
    <select name="options" disabled>
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Selected option

<span class="select">
    <select name="options">
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
        <span class="select__icon"></span>
    </select>
</span>
        

Unselected Select

If no suitable default value exists, the first option in the list can be used as a prompt and set to disabled & selected.

<span class="select">
    <select>
        <option value="0" disabled selected>-select-</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Fluid select

<span class="select select--fluid">
    <select name="options" id="options">
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Borderless select

<span class="select select--borderless">
    <select name="options" id="options">
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Borderless, disabled select

<span class="select select--borderless">
    <select name="options" id="options" disabled>
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Right-to-left select

<span class="select" dir="rtl">
    <select name="options" id="options">
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
        

Foreground icon select

<span class="select">
    <select name="options" id="options">
        <option value="item1">Option 1</option>
        <option value="item2" selected>Option 2</option>
        <option value="item3">Option 3</option>
    </select>
    <svg aria-hidden="true" class="select__icon" focusable="false">
        <use xlink:href="#icon-settings"></use>
    </svg>
</span>
        

Small Select (DS4 Only)

For a small select, apply the select--small modifier.

<span class="select select--small">
    <select>
        <option value="0" disabled selected>Choose a Size</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
    

Large Select (DS4 Only)

For a large select, apply the select--large modifier.

<span class="select select--large">
    <select>
        <option value="0" disabled selected>Choose a Size</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>
    <span class="select__icon"></span>
</span>
    

@ebay/skin/spinner

A spinner animation is used to convey a busy or loading state.

A spinner is considered a critical graphic, therefore an img role and aria-label property are required.

<span class="spinner" aria-label="Busy animation" role="img"></span>
    

Large Spinner

Use the spinner--large modifier class to create a large spinner.

<span class="spinner spinner--large" aria-label="Busy" role="img"></span>
    

@ebay/skin/svg

The SVG module imports an external SVG source containing all symbol definitions. However, due to a lack of browser support for external SVG definitions, we recommend not using this module for now and instead inlining (i.e. copy & pasting) all required definitions from below into a hidden SVG block on your page.

Please view the icon module for instructions on how to reuse and display these symbols anywhere on the page.

@ebay/skin/switch

A switch behaves like a checkbox - it can be on or off (i.e checked or unchecked) - and under the hood, that's exactly what it is. Whereas checkboxes are often used to allow multi-selection from a group of choices, switches are more often used in isolation or as a series of unrelated options.

REMEMBER: every switch requires a visible label! Please see the field module for details on labelling controls.

<span class="switch">
    <input class="switch__control" role="switch" type="checkbox" />
    <span class="switch__button"></span>
</span>
    

Disabled Switch

<span class="switch">
    <input class="switch__control" role="switch" type="checkbox" disabled />
    <span class="switch__button"></span>
</span>
    

@ebay/skin/tab

A tab allows the user to switch between multiple panels of content. By decluttering the user-interface in this way, we say that tabs follow the principal of progressive disclosure.

Selecting a tab should update the visible panel without a full page reload. If a full page load is required instead (i.e. acting like a link), please see the fake tab section below for more details.

Default Tabs

When a tab is selected, the aria-selected state of all tabs in the list must be updated in order for the CSS to reflect the change. Only one tab can be selected and in the tab order at any moment in time. Likewise, only one tabpanel can be visible at any time, and it must correspond to the currently selected tab.

Use child element modifier tabs__items--large to opt into larger font-size for tabs.

NOTE: JavaScript is required to handle tab selection state, panel visibility, focus management and arrow-key navigation. For detailed behaviour requirements, please visit the eBay MIND Pattern for Tabs.

Panel 1 Content

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

<div class="tabs">
    <div class="tabs__items" role="tablist">
        <div aria-controls="default-tabpanel-1" aria-selected="true" class="tabs__item" id="default-tab-1" role="tab">
            <span>Tab 1</span>
        </div>
        <div aria-controls="default-tabpanel-2" aria-selected="false" class="tabs__item" id="default-tab-2" role="tab">
            <span>Tab 2</span>
        </div>
        <div aria-controls="default-tabpanel-3" aria-selected="false" class="tabs__item" id="default-tab-3" role="tab">
            <span>Tab 3</span>
        </div>
    </div>
    <div class="tabs__content">
        <div aria-labelledby="default-tab-1" class="tabs__panel" id="default-tabpanel-1" role="tabpanel">
            <div class="tabs__cell">
                <h3>Panel 1 Content</h3>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?</p>
            </div>
        </div>
        <div aria-labelledby="default-tab-2" class="tabs__panel" hidden id="default-tabpanel-2" role="tabpanel">
            <div class="tabs__cell">
                <h3>Panel 2 Content</h3>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?</p>
            </div>
        </div>
        <div aria-labelledby="default-tab-3" class="tabs__panel" hidden id="default-tabpanel-3" role="tabpanel">
            <div class="tabs__cell">
                <h3>Panel 3 Content</h3>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?</p>
            </div>
        </div>
    </div>
</div>
    

Fake Tabs

A fake tab looks like a normal tab, but is actually a hyperlink to a new page. Therefore a set of fake tabs behaves more like a simple navigational widget, rather than a dynamic user interface control.

A valid HREF attribute is required for all anchor tags. A value of "javascript" (or any such variant) is not a valid URL!

The fake-tabs__item--current class is used to visually denote the current link. The aria-current attribute is used to programmatically denote the current page state.

Use child element modifier fake-tabs__items--large to opt into larger font-size for fake tabs.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

<div class="fake-tabs">
    <ul class="fake-tabs__items">
        <li class="fake-tabs__item fake-tabs__item--current">
            <a aria-current="page" href="http://www.ebay.com">Page 1</a>
        </li>
        <li class="fake-tabs__item">
            <a href="http://www.ebay.com">Page 2</a>
        </li>
        <li class="fake-tabs__item">
            <a href="http://www.ebay.com">Page 3</a>
        </li>
    </ul>
    <div class="fake-tabs__content">
        <div class="fake-tabs__cell">
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet assumenda culpa est nisi porro quae quidem ratione repellendus, temporibus. Assumenda atque dolor dolorem eligendi eveniet ipsam modi necessitatibus quos ut?</p>
        </div>
    </div>
</div>
    

@ebay/skin/textbox

A textbox (also known as an input) allows the user to enter data.

The purpose of a textbox is to collect form data. Therefore, textbox should always be used in conjunction with a form, label and submit button.

IMPORTANT: The examples below show the textbox in isolation, without any label. Remember: every textbox requires a label!

Single-Line Textbox

Use an input tag for a single-line textbox.

<span class="textbox">
    <input class="textbox__control" type="text" placeholder="placeholder text" />
</span>
    

Disabled Textbox

Use the disabled attribute to disable any input.

<span class="textbox">
    <input class="textbox__control" type="text" placeholder="placeholder text" disabled />
</span>
    

Textbox with error

Use the aria-invalid attribute to highlight any input with error.

<span class="textbox">
    <input class="textbox__control" type="text" placeholder="placeholder text" aria-invalid="true" />
</span>
    

Multi-line Textbox

Use the textarea tag for a multi-line textbox.

A multi-line textbox allows line breaks and has a minimum height of 200px.

<span class="textbox">
    <textarea class="textbox__control" placeholder="placeholder text"></textarea>
</span>
    

Fluid Textbox

Apply the textbox__control--fluid modifier (or fluid utility class) to fill the width of the parent element.

<div class="textbox">
    <input class="textbox__control textbox__control--fluid" type="text" placeholder="placeholder text" />
</div>
    

Textbox with Icon

Single-line textboxes can be augmented with any inline SVG icon, using a textbox__icon element before the control. Font-icons are no longer supported.

<span class="textbox">
    <svg aria-hidden="true" class="textbox__icon" focusable="false" width="16" height="16">
        <use xlink:href="#icon-mail"></use>
    </svg>
    <input class="textbox__control" type="text" placeholder="placeholder text" />
</span>
    

Use textbox--icon-end modifier to position the icon after the control.

<span class="textbox textbox--icon-end">
    <input class="textbox__control" type="text" placeholder="placeholder text" />
    <svg aria-hidden="true" class="textbox__icon" focusable="false" width="16" height="16">
        <use xlink:href="#icon-mail"></use>
    </svg>
</span>
    

NOTE: The icon is presentational, and therefore hidden from assistive technology using aria-hidden. Remember, the purpose of the field must be conveyed using a label.

Underline Textbox

Use textbox__control--underline modifier to style the textbox with only a bottom border to be used in conjuction with floating labels.

Please see the label module for details on labelling controls. Remember: every textbox requires a label!

<span class="textbox">
    <input class="textbox__control textbox__control--underline" type="text" />
</span>
    

@ebay/skin/tooltip

A tooltip is a flyout that visually points to a specific section or element of the page.

The DOM order of flyout elements is very important! To avoid keyboard and screen reader accessibility issues, the flyout element must immediately follow the element that it points to.

For all tooltips, the pointer element is positioned at the top and center by default, but can be positioned using any of the following modifiers:

NOTE: In order to achieve optimal placement, both for the overlay and it's pointer, JavaScript will be required.

Default Tooltip

The default tooltip, is the classic desktop tooltip that activates on focus and hover of a clickable element (typically an icon button or link). The purpose of the classic tooltip is to inform the user about the clickable element.

The default tooltip must be programmatically associated with it's clickable element by using the aria-describedby property and tooltip role.

Toggle the aria-expanded state of the clickable element to expand or collapse it's tooltip.

<span class="tooltip">
    <button accesskey="s" class="tooltip__host icon-btn" aria-describedby="tooltip-0" aria-expanded="false" aria-label="Settings">
        <svg class="svg-icon" focusable="false" height="16" width="16" aria-hidden="true">
            <use xlink:href="#icon-settings"></use>
        </svg>
    </button>
    <div class="tooltip__overlay" id="tooltip-0" role="tooltip">
        <span class="tooltip__pointer tooltip__pointer--bottom-left"></span>
        <div class="tooltip__mask">
            <div class="tooltip__cell">
                <div class="tooltip__content">
                    <p>Use Access Key 'S' to display settings.</p>
                </div>
            </div>
        </div>
    </div>
</span>
    

Infotip

An infotip is a standalone button that activates only on click. The purpose of the infotip is to inform the user about a non-clickable element or page section.

Toggle the aria-expanded state of the button to expand or collapse the infotip.

Infotip

Here's a tip to help you be successful at your task.

<span class="infotip">
    <button class="icon-btn infotip__host" type="button" aria-expanded="false" aria-label="Help">
        <svg aria-hidden="true" class="svg-icon" focusable="false" width="16" height="16">
            <use xlink:href="#icon-information"></use>
        </svg>
    </button>
    <div class="infotip__overlay">
        <span class="infotip__pointer infotip__pointer--top-left"></span>
        <div class="infotip__mask">
            <div class="infotip__cell">
                <span class="infotip__content">
                    <h3 class="infotip__heading">Infotip</h3>
                    <p>Here's a tip to help you be successful at your task.</p>
                </span>
                <button aria-label="Dismiss infotip" class="infotip__close" type="button">
                    <span aria-hidden="true" role="img"></span>
                </button>
            </div>
        </div>
    </div>
</span>
    

Tourtip

A tourtip is open by default and must be explcitly closed using a button. Once closed, it cannot be reopened. The purpose of the tourtip is to inform the user of some new feature or section on the page.

Toggle the tourtip--expanded modifier to expand or collapse the tourtip.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Tourtip

Here's something new to help you be successful at your task.

<div class="tourtip tourtip--expanded">
    <p class="tourtip__host">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <div class="tourtip__overlay" role="region" aria-labelledby="tourtip-label">
        <span class="tourtip__pointer tourtip__pointer--left"></span>
        <div class="tourtip__mask">
            <div class="tourtip__cell">
                <span class="tourtip__content">
                    <h2 class="tourtip__heading" id="tourtip-label">Tourtip</h2>
                    <p>Here's something new to help you be successful at your task.</p>
                </span>
                <button aria-label="Dismiss tourtip" class="tourtip__close" type="button">
                    <span aria-hidden="true" role="img"></span>
                </button>
            </div>
        </div>
    </div>
</div>

@ebay/skin/typography

Static sites without access to the LESS preprocessor can leverage the Skin type ramp via the typography module.

  • .giant-text-2
  • .giant-text-1
  • .large-text-2
  • .large-text-1
  • .medium-text
  • .regular-text
  • .small-text

With the exception of giant text, which is always bold, all other entries in the type ramp can be set to bold-text or secondary-text by adding the relevant class.

  • .large-text-2 .bold-text
  • .large-text-2 .secondary-text

@ebay/skin/utility

The utility module provides a small set of common, utility classes. It is not intended as an exhaustive library of utility classes or functions (i.e. it is not Funcssion!).

Typically these classes will not conflict with styles set by BEM, and in some cases are applied directly by our Experience Service backend.

Utility Classes
Class Properties Class Properties
.clearfix Clear floated elements .truncate Truncate single-line text
.clipped Element visible to screen reader only .clipped--stealth Clipped element becomes visible on focus (modifier)
.fluid-image Image will stretch up and down .responsive-image Image will scale up and down
.no-scroll overflow: hidden; .no-wrap white-space: nowrap;
.image-wrapper Vertically and horizontally center an image .fluid width: 100%;
.positive Positive text color (green) .negative Negative text color (red)
.emphasis Emphasis text color (red)