TED Swatch

A living guide to the styles, helpers, and widgets used to produce the TED.com site.

Page layout: Containers & Grids

The most basic components used to lay out a TED.com page.

Containers

Content, including grids, should generally be wrapped by a block element having a CSS container class. The container is centered in the page and given horizontal padding and a maximum width to make sure their content is aligned correctly, leaving a gutter for comfortable reading on all screen sizes.

Example use (HAML):

.container
  %p Some text

Introduction to grids

TED's 12-column responsive grid system can be used to produce a variety of columnar page layouts across screen sizes. The premise of a grid system is similar to designing with HTML tables: the grid consists of rows, each row consists of 12 columns. A single element can span anywhere between 1 and 12 of those columns.

For example:

6
6
3
3
3
3
.container
  .row
    .col-sm-6
      6
    .col-sm-6
      6

  .row
    .col-sm-3
      3
    .col-sm-3
      3
    .col-sm-3
      3
    .col-sm-3
      3

Aside from not being criminally bad semantics, this grid system has some unique advantages over HTML tables. On small screen sizes like phones, for example, the columns in the above demo (which normally take up a fluid amount of width as available) "collapse" so that each column takes up the full width of the device. That way, columns never become too narrow. You can resize your browser window to see this effect.

You can tweak the breakpoint at which a column collapses, and the size it collapses to, by targeting column spans at size groups. Th "-sm-" in the class names you see above do exactly this. The anatomy of a grid column CSS class is:

.col-{{size group}}-{{span}}

For example, if you resize your screen, you'll notice that the red boxes below stay stacked in a row except at the very smallest screen sizes, whereas the second set of gray boxes collapses into individual rows as soon as the browser becomes narrower than 1024px:

4
4
4
4
4
4

Three different size groups exist:

Class prefix Breakpoint: Explanation:
.col-xs- 480px Takes effect at screen sizes equal to and above 480px. Columns will be "collapsed" into a vertical list at smaller screen sizes.
.col-sm- 768px Takes effect at screen sizes equal to and above 768px.
.col-lg- 1024px Takes effect at screen sizes equal to and above 1024px.

Combining grid size groups

You can combine multiple size group classes on the same element. For example, in the demonstration below, the sidebar element spans 4 columns at the "xs" breakpoint, but only 3 columns at the "lg" breakpoint:

Sidebar
Content
.container
  .row
    .col-sm-4.col-lg-3
      Sidebar
    .col-sm-8.col-lg-9
      Content

Grid offsets

At grid sizes "sm" and above, you can specify "offsets" by adding an offset CSS class to your span element. An offset allows you to pad your grid with empty columns without having to introduce empty HTML elements.

For example:

4
4 offset 4
3 offset 3
3 offset 3
6 offset 6
.container
  .row
    .col-sm-4
      4
    .col-sm-4.col-sm-offset-4
      4 offset 4
  .row
    .col-sm-3.col-sm-offset-3
      3 offset 3
    .col-sm-3.col-sm-offset-3
      3 offset 3
  .row
    .col-sm-6.col-sm-offset-6
      6 offset 6

Like the column classes themselves, offset classes can be targeted at specific size groups. The anatomy of an offset class is:

.col-{{size group}}-offset-{{span}}

{{span}} indicates the number of columns to offset the element by.

Grid nesting

It's possible to nest grid rows within columns.

12
6
6
6
6
.container
  .row
    .col-lg-12
      12
      .row
        .col-lg-6
          6
          .row
            .col-lg-6
              6
            .col-lg-6
              6
      .col-lg-6
        6

Demonstration of grid sizes

This section contains some demonstrations to help you picture what grids look like at their absolute narrowest.

Please note that these demonstrations have been artificially capped to show you what grids look like at the breakpoints where each size group takes over.

Example: extra small grid columns at their narrowest
4
4
4
Example: small grid columns at their narrowest
2
2
2
2
2
2
4
4
4
Example: large grid columns at their narrowest
1
1
1
1
1
1
1
1
1
1
1
1
4
4
4

Evenly divided "n-up" grids

An alternative n-up grid system also exists in Roadrunner. This system divides a row's columns evenly, with the divisor specified at the row level instead of the column level. For example:

.container
  .row.row-sm-4up.row-lg-6up
    .col Item 1
    .col Item 2
    .col Item 3
    .col Item 4
    .col Item 5
    .col Item 6
    .col Item 7
    .col Item 8
    .col Item 9
    .col Item 10
    .col Item 11
    .col Item 12

The 12 items will be divided evenly into 3 rows of 4 columns at the "sm" (768px) breakpoint and into 2 rows of 6 columns at the "lg"(1024px) breakpoint. This approach isn't as versatile as the general grid system, but can be useful for simplifying horizontal search result layouts, etc.

This table (below) shows which divisions are available at which breakpoints. Per the example above, multiple classes may be specified for the same row to divide columns differently at different breakpoints.

2up 3up 4up 5up 6up
.row-xs-
.row-sm-
.row-lg-

Except on older browsers (IE 8 and below), this grid system without requiring the use of clearfixes:

Example: "n-up" grids
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo buffalo buffalo.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Buffalo buffalo buffalo Buffalo buffalo.

Typography

Headings

Here is an index of classes to use for headings. Each style is prefixed by its CSS .class name:

Happy talks
The death of innovation, the end of growth
Beyond the talk
What information do we collect?
Providing requested services
Erik Brynjolfsson: The key to growth? Race with the machines
Why I must speak out about climate change
What to watch next
The creative spark
Show 20 more talks
James B. Glattfelder, Legal Activist
Areas of Expertise
Information you provide directly to us

When pairing a heading with a decorative link floated beside it, please use the heading helper.

Margins

Because margin use below headings depends on context, the default heading classes do not include any margins. Please use one of these classes to add margins below your headings:

CSS class Mobile bottom-margin Desktop bottom-margin
.m1 20px 40px
.m2 20px 30px
.m3 20px 20px
.m4 10px 10px
.m5 5px 5px

Paragraphs

Here is an index of classes to use for paragraph text. Each style is prefixed by its CSS .class name:

The US economy has been expanding wildly for two centuries. Are we witnessing the end of growth? Economist Robert Gordon…
Overall business growth is limited; instead, growth is limited to categories that shift based on demand.
Share your thoughts with the TED community and see what others are saying
What is this thing you've stumbled upon? "TED"? Talks on riveting ideas: Technology, Entertainment, Design and so much more. Here's a TED primer, featuring 11 classic talks on a full range of topics.

Standalone links

Each style is prefixed by its CSS .class name:

Miscellaneous typographic styles

Each style is prefixed by its CSS .class name:

You don't wake up one day no longer a racist. It takes generations to tear that intuition.
All of the great Disney works took works that were in the public domain and remixed them.
14m 28s • Views 1,245,689
Opposing view:
Follow these talk topics:
Etiam at risus et justo dignissim congue.

Custom font size mixins

To make the site accessible for users who need to set custom fonts or sizes, we try to provide support for rem units wherever possible. rem units adjust the font size relative to the user's browser settings. Some Sass mixins are included that make working with rem units a cinch.

To set the font size without setting a line height, or while setting a relative line height (i.e., a line height without unit specified or with a relative unit such as ems specified), please use the font-size mixin, and provide it a pixel font size:

.my-class {
  @include font-size(14px);
  line-height: 1.4;
}

Please make sure you only use pixel units with this mixin. Other units are not currently supported.

To set both font size and line height in pixels, please use the font-line mixin:

.my-class {
  @include font-line(14px, 20px);
}

This (above) example will produce a font-size of 14px and a line height of 20px.

Colors

Sass variables are available for standard colors and gradients.

Plain colors

Variables

Note that we intentionally avoid true black (#000000) because of its unnatural appearance on locally dimmed LED screens. Please prefer $natural-black instead.

$natural-black
$darker-gray
$dark-gray
$gray
$light-gray
$lighter-gray
$white
$ted-red

Class Names

When possible, use class names to apply colors. The following class names can be used, with the mnemonics "bg" for background and "fg" for foreground.

fg-black
fg-dark-gray
fg-natural-black
fg-darker-gray
fg-dark-gray
fg-gray
fg-light-gray
fg-lighter-gray
fg-white
fg-red
bg-black--75
bg-black--66
bg-black--50
bg-black--33
bg-black--25
bg-black--10
bg-black
bg-darker-gray
bg-dark-gray
bg-gray
bg-light-gray
bg-lighter-gray
bg-white
bg-red
fg-black--hover
fg-darker-gray--hover
fg-dark-gray--hover
fg-gray--hover
fg-light-gray--hover
fg-lighter-gray--hover
fg-white--hover
fg-red--hover
bg-black--hover
bg-darker-gray--hover
bg-dark-gray--hover
bg-gray--hover
bg-light-gray--hover
bg-lighter-gray--hover
bg-white--hover
bg-red--hover

Gradients

Use these variables with the standard CSS background-image property. For example:

background-image: $ted-red-grad;
$ted-red-grad
$light-grad
$dark-grad

Buttons & Forms

Inputs

Input styles are included in the default form styles:

%input.form-control{value: 'Test text'}

You can also add icons to inputs:

.input-overlay
  %input.form-control{placeholder: 'Search…'}
  .input-overlay__addon= icon 'search'

Dropdowns

Dropdown styles are included in the default form styles:

%select.form-control.form-control--dropdown
  %option Option 1
  %option Option 2
  %option Option 3
  %option Option 4

Form Groups & labels

Form elements and their labels can be grouped together:

.form-group
  = label_tag 'message[email]', "Email", class: 'form-label form-label--required'
  = text_field_tag 'message[email]', nil, class: 'form-control', required: true

.form-group
  = label_tag 'message[subject]', "Subject", class: 'form-label form-label--required'
  = text_field_tag 'message[subject]', nil, class: 'form-control', required: true

Buttons

Button styles are not included by default. To add button files to your app scss file, please inlcude the following BEM block:

@import "bem-blocks/buttons"

To create a button, simply add the button CSS class to an element:

%button.button Button

This class can be applied to any element, not just HTML button elements. You can also use it on anchors (links) for example.

The modifier class button--medium gives a slightly darker background -- good for use over gray page backgrounds.

%button.button.button--medium Medium button

The modifier class button--blue gives the button light text on a blue background:

%button.button.button--blue Blue button

The modifier class button--red gives the button light text on a red background:

%button.button.button--red Red button

The modifier class button--dark gives the button light text on a dark background:

%button.button.button--dark Dark button

The modifier class button--wide makes the button a block-level element:

%button.button.button--wide Wide button

Combo (dropdown with input)

A combo jQuery UI widget is available and can be applied to standard select boxes:

%select.form-control.form-control--dropdown#combo
  %option{value: ''} Please select a language
  %option{value: 'JavaScript'} JavaScript
  %option{value: 'PHP'} PHP
  %option{value: 'Ruby'} Ruby

$('#combo').combo({
  source: [
    'ActionScript', 'AppleScript', 'Asp', 'BASIC',
    'C', 'C++', 'Clojure', 'COBOL', 'ColdFusion',
    'Erlang', 'Fortran', 'Groovy', 'Haskell',
    'Java', 'JavaScript', 'Lisp',
    'Perl', 'PHP', 'Python', 'Ruby',
    'Scala', 'Scheme'
  ]
});

Please be sure to include the 'lib/widgets/combo' AMD dependency in your JavaScript when you want to use the combo widget, and the 'blocks/combo' dependency in your Sass.

Layout components

Media

The media component is useful whenever you have an image with a block of text sitting next to it.

(Image)
This text will appear to the right of the image.
.media
  .media__image
    (Image)
  .media__message
    This text will appear to the right of the image.

Can also be used when the media item should appear on the right (rather than left) of the text:

(Image)
This text will appear to the left of the image.
.media
  .media__image--alt
    (Image)
  .media__message
    This text will appear to the left of the image.

It's also possible to have the floating behavior triggered at certain breakpoints, or disabled until a certain breakpoint:

(Image)
This text will appear to the left of the image on large screens and below the image on small screens.
.media.media--oh-v.media--lg-h
  .media__image
    (Image)
  .media__message
    This text will appear to the left of the image
    on large screens and below the image on small
    screens.
(Image)
This text will appear below the image on large screens and to the left of the image on small screens.
.media.media--lg-v
  .media__image
    (Image)
  .media__message
    This text will appear below the image on large
    screens and to the left of the image on small
    screens.

When using the media component with the the thumbnail helper, add the CSS modifier class media__image--thumb to the media__image object:

.media
  .media__image.media__image--thumb
    = thumb 'image.jpg'
  .media__message
    Message text.

Lists

Ordered and unordered lists are rendered using the Browser's default styles to avoid reproducing rules unnecessarily. When producing a list that should be "reset" to remove the default margins, padding, and bullets, please add the sl ("semantic list") class to the <ul> or <dl> tag:

%ul.sl
  %li ...

An additional CSS block provides a common style for lists. It can be applied to any HTML structure by giving the parent element the class list and child list items the class list__item:

  • First item
  • Second item
  • Third item
%ul.sl.list
  %li.list__item
    First item
  %li.list__item
    Second item
  %li.list__item
    Third item

Thumbnails

The thumb helper sets up an image container in the correct aspect ratio before the image has loaded; controlling the image size with clipping and creating a smoother experience for users while the page is loading.

When linking to a talk, simply add the CSS class play-link to the link wrapper you use.

If using the thumb helper within a media component, please note the special usage requirements.

Examples:

16:9 (default) thumb intended for use with talk images.
= thumb thumb_url
Square thumb intended for use on playlist and people images.
= thumb thumb_url, ratio: :square
4:3 thumb for use with legacy images.
= thumb thumb_url, ratio: :tv

By default, the image side of the media component makes up 30% of its total width when the two are displayed side-by-side, or 100px at mobile breakpoints.

Decorated headings

The heading helper produces output for a common lockup: a heading (of any of the standard heading classes) decorated with a link aligned to its baseline:

Heading text
Link text
= heading 'Heading text',
  link: 'Link text',
  href: '#compontents-headings'

Additional options can be used to configure the heading class and link target:

Heading text
Link text
= heading 'Heading text',
  link: 'Link text',
  href: '#compontents-headings',
  class: 'h2',
  target: '_blank'

Putting it all together

This example combines some of the components and typographic rules described above to show how they can be used together:

Heading
Link
Eyebrow

Title

Attribute Value • Attribute Value
Eyebrow

Title

Attribute Value • Attribute Value
Eyebrow

Title

Attribute Value • Attribute Value
= heading 'Heading',
  link: 'Link',
  href: '#components-together'

.list
  - 3.times do
    %article.list__item
      .media
        .media__image.media__image--thumb
          = thumb thumb_url
        .media__message
          .e1 Eyebrow
          %h3.h7.m5 Title
          .meta
            Attribute
            %span.meta__val Value
            &bull;
            Attribute
            %span.meta__val Value

Icon fonts

TED uses an icon font to produce scalabale, vector-based icons throughout the site.

Here is a complete list of the currently available icons:

action-attend
action-connect
action-download
action-follow
action-join
action-learn
action-organize
action-participate
action-petition
action-quote
action-share
action-signup
action-subscribe
action-visit
action-volunteer
arrow-alt-left
arrow-alt-right
arrow-left
arrow-right
barchart
checkmark
circle-check
circle-download
circle-email-fill
circle-email
circle-embed-fill
circle-embed
circle-facebook-fill
circle-facebook
circle-favorite-fill
circle-favorite
circle-googleplus
circle-help-fill
circle-ig-fill
circle-left
circle-linkedin
circle-more-fill
circle-more
circle-play
circle-rate
circle-right
circle-share
circle-twitter-fill
circle-twitter
circle-watchlater-fill
circle-watchlater
close-small
control-cog
control-fullscreen-exit
control-fullscreen
control-mute
control-pause
control-play
control-playlist
control-skip
control-subtitles
control-transcript
control-unskip
control-volume
corrections
facebook
flag
flickr
footnotes
item-book
item-globe
item-speaker
item-text
item-video
link
message
outbound
page-dot-off
page-dot-on
pencil
photo-credits
photo
pin
reading-list
reply
search
subtitle
transcript
twitter
upvote
x
youtube

Use in HAML

To include icons in your HAML, please use the icon helper:

= icon 'arrow', 'Arrow label'

The first parameter should be the icon's name, per the icon grid above.

The second parameter is a label. This won't be rendered visibly, but will be announced by screen readers parsing the HTML output. It's only necessary when your icon is otherwise unlabeled.

You can also include an options object with an additional CSS class to be added to the icon element:

= icon 'arrow', :class => 'my-arrow'

Use in Handlebars (JavaScript templating)

A Handlebars helper is also available:

{{icon 'arrow'}}

The Handlebars helper supports two more parameters: a screen reader label (like the markdown helper), and any additional CSS classes as a string:

{{icon 'arrow' 'Arrow Label' 'my-arrow'}}

If you'd like to include an additional CSS class but don't need a screen reader label, please use an empty string as the second parameter:

{{icon 'arrow' '' 'my-arrow'}}

Sass mixins

By default, icons are sized at 40px. To change their size, please give them a special CSS class (using the helpers above) and then target that class in your Sass to specify a size using the icon-size mixin:

.my-arrow {
  @include icon-size(60px);
}

Comments & Conversations

Styles and JS widgets to use for comments and conversations.

JS comments

2000 characters remaining
Please log in or sign up to add comments.

Styles & read-only server-side use

The comment styles are not included by default. If you need to add comments to a page, please import the necessary Sass block from your application stylesheet:

@import "bem-blocks/comments"

To display a thread of comments with these styles, please use the comments helper. Simply set up an array in the following format:

[
  # Object for each comment
  {
    name: 'String',
    profile_id: 'String',
    date: Date,
    message: 'String',
    replies: Array # array of comments
  }
]

The replies array should be in the same format.

Pass this array to the comments helper in your view:

= comments comments_array

Misc Styles

Stubs

Stubs can be used to provide filters, editable tag lists, etc.

Stub nameRemove
= stub('Stub name')

Miscellaneous JavaScript widgets

Tag select

Please select
Tag One Tag Two

Tag builder

Tag One Tag Two

Carousels

A Backbone View and accompanying CSS exists for creating carousels.

define([
  'Backbone',
  'lib/views/CarouselView',
  'hbs!lib/templates/myItemTemplate'
], function (
  Backbone,
  CarouselView,
  carouselItemTemplate
) {
  var carouselItems = new Backbone.Collection();

  carouselItems.add([
    {
      name: 'Item 1',
      description: 'Item description.'
    },
    {
      name: 'Item 2',
      description: 'Item description.'
    }
    // ...and so on
  ]);

  var carouselView = new CarouselView({
    el: document.getElementById('carousel'),
    collection: carouselItems,
    itemTemplate: carouselItemTemplate
  });

  carouselView.render();
});

Modals

Please include the lib/frontend/widgets/modal JS dependency and the blocks/modal Sass dependency to display modals.

This is a demonstration modal.

#modal
  .modal__head
    %a.modal__close.modal__head__close{href: '#'}
      %i.g-button-modal-close Close
    %h3modal__head__title Demo modal
  %p This is a demonstration modal.

%button.button#button Click me

%script
  var $modal = $('#modal').modal({
    autoOpen: false
  });

  $('#button').on('click', function () {
    $modal.modal('open');
  });

Tooltips

Please include the lib/widgets/tooltip JS dependency and the blocks/tooltip Sass dependency to display tooltips.

Always remember that, due to the limitation of touch screens, an element that already performs some other action on click cannot also function as a tooltip. e.g., links and buttons cannot be tooltips unless that is their only function.

%button.button#tooltip Hover/tap me to show a tooltip.

$('#tooltip-1').tooltip({
  content: 'This text is displayed in a tooltip.'
});

$('#tooltip-2').tooltip({
  content: 'This text is displayed in a tooltip.',
  inverse: true
});