Style Guide

Our Philosophy

The goal of this style guide is to create a front-end framework to maintain consistency across News Apps projects, while giving each designer and developer the flexibility to code in their own unique and creative way. These styles provide a starting point for visual graphics and larger projects, and aren't intended to be the basis for an entire site design.

Our style files are written in SCSS — a Sass syntax that builds on the existing CSS syntax. With SCSS, we can use all the great features of Sass, such as @mixins, %placeholders and $variables, but can write in the more familiar (and more expressive) CSS syntax.

If you're unfamiliar with Sass or SCSS, read this guide to catch up on the basics.

Currently, our partial style files are broken into three folders — helpers, theme, and components. You'll find a thorough description of the partials in the helpers folder below. If you're creating a feature with additional prose styles or making a graphic, you may also want to use those partials from the theme folder. And you'll find particular styles for components, like a masthead, and footer, in the components folder.

The Helpers

Everything you need to jump start a project is contained in the helpers folder. Here's a quick explanation of each of the partials:

_base.scss

These are the only styles applied directly to HTML elements. If you really need a clean slate, don't use this partial. It's helpful for normalizing styles and inheriting basic news apps prose styles without using additional classes.

_buttons.scss:

Creates a button mixin, to include buttons in any color. Also allows for solid color buttons or ghost buttons, based on the arguments you insert.

_colors.scss:

All of our colors are assigned to $variables, most of which have a descriptive name to help you decide when to use it. For example, $rep-red and $dem-blue are used for typical political party designations.

_grid.scss:

Mixins, breakpoint variables and classes to help you build a responsive layout are included in the grid partial. Jump to Grid Specs to learn more about the basic structure and default grid settings, and Grid Mixins to learn more about the @mixins we've created to help you implement a grid design.

_tables.scss:

This partial contains one mixin to rule them all — i.e. all the variations of mobile table styles. Skip to Tables to learn more.

_typography.scss:

Our style guide has a modular typography system. By changing the size $variables, you can change font-sizes across the entire project. The system also allows you to designate font-size with .classes in your HTML or @extend %font-sizes on new classes.

Colors

Tribune Colors

  • $tribune-yellow

    #FFC200

    rgb(255, 194, 0)

  • $tribune-teal

    #008990

    rgb(0, 137, 144)

Party Colors

  • $dem-blue

    #1775AE

    rgb(23, 117, 174)

  • $rep-red

    #D64946

    rgb(214, 73, 70)

Shades of Gray

  • $black

    #000

    rgb(0, 0, 0)

  • $tribune-black

    #111

    rgb(17, 17, 17)

  • $bodytext-black

    #282828

    rgb(40, 40, 40)

  • $text-gray

    #666

    rgb(102, 102, 102)

  • $line-gray

    #BBB

    rgb(187, 187, 187)

  • $border-gray

    #CCC

    rgb(204, 204, 204)

  • $href-offwhite

    #DDD

    rgb(221, 221, 221)

  • $background-gray

    #F5F5F5

    rgb(245, 245, 245)

  • $white

    #FFF

    rgb(255, 255, 255)

Graphic Colors

  • $orange

    #FF6249

    rgb(255, 98, 73)

  • $light-orange

    #FFD454

    rgb(255, 212, 84)

  • $purple

    #9772C5

    rgb(151, 114, 197)

  • $green

    #8DC967

    rgb(141, 201, 103)

  • $blue

    #8DC967

    rgb(74, 161, 204)

  • $light-blue

    #90D3C8

    rgb(144, 211, 200)

Grid Specs

The grid specs are located in helpers/_grid.scss. The News Apps graphic and app kits include the Bourbon Neat semantic grid framework.

To include an element in a responsive grid design, add the class .container to the parent-most HTML element. We've overriden Bourbon's $max-width to 1081px, which is typical for our app projects. To change how wide the grid can stretch, set the variable $max-width in your project.

Content-Block

Content-blocks are used to ensure that an element does not bump against the edge of the screen on smaller devices or window-sizes. Add the class .content-block to add a 10px left/right margin at all times, or add "@extend %content-block" to the parent-most element's styles.

      
        %content-block,
        .content-block {
          @include pad(0 10px);
        }
      
    

Breakpoints

For ease of use, we've created two types of default breakpoints — both of which you can override to best fit your project. There are $default-mobile and $default-desktop, which set max and min widths, respectively. And there are $small, $medium and $large default breakpoints for mobile-first web design with multiple layouts. All of these variables can be overriden for your specific project needs.

Some modules also have a unique breakpoint variable included at the top of the file, which is set to $default-desktop or $default-mobile. You can change the module's breakpoint by giving that variable a new value.

      
        $default-desktop: new-breakpoint(min-width 768px);
        $default-mobile: new-breakpoint(max-width 480px);

        $small: new-breakpoint(min-width 460px max-width 810px);
        $medium: new-breakpoint(min-width 811px max-width 1080px);
        $large: new-breakpoint(min-width 1081px);
      
    

Grid Mixins

Bourbon Neat has a variety of built-in mixins that you should use to create the grid. In addition, we've added mixins that you may find useful. These can be found in helpers/_mixins.scss.

Bourbon's Neat Mixins

Read Bourbon Neat's documentation for a full explanation. These are some of the @mixins you'll use most often.

Clearfix

Bourbon Neat's grid mixins add floats to HTML elements, so they'll sit in the grid properly. Sometimes, you'll need to clear these floats, so that your content doesn't accidentally overlap.

      
        @mixin clearfix {
          &:after {
           visibility: hidden;
           display: block;
           font-size: 0;
           content: " ";
           clear: both;
           height: 0;
         }
        }
      
    

Omega Reset

Occasionally you'll need to reset Bourbon Neat's count of elements, so that it will add @mixin omega() to the correct element. The @mixin omega-reset is adapted from Josh Fry's example, and you can find more info here.

      
        @mixin omega-reset($nth) {
          &:nth-child(#{$nth}) { margin-right: flex-gutter($grid-columns, $gutter); }
          &:nth-child(#{$nth}+1) { clear: none }
        }
      
    

Mobile vs. Desktop Mixins

Sometimes you'll want to hide an element on Desktop or Mobile. We've created a series of mixins to help:

  • @mixin hide($breakpoint) — hide content at any given breakpoint.
  • @mixin mobile-only() — display on mobile, hide content on default $small, $medium and $large breakpoints.
  • @mixin desktop-only() — hide on mobile, display content on default $small, $medium and $large breakpoints.
  • @mixin desktop-hide() — display on mobile and default $small breakpoint, hide on default $medium and $large breakpoints.
  • @mixin mobile-hide() — hide on mobile and default $small breakpoint, display on default $medium and $large breakpoints.
      
// Mobile vs. Desktop Mixins
// =========================

@mixin hide($bp) {
  @include media($bp) {
    display: none;
  }
}

@mixin mobile-only {
  display: block;

  @include media($small) {
    display: none;
  }

  @include media($medium) {
    display: none;
  }

  @include media($large) {
    display: none;
  }
}

@mixin desktop-only {
  display: none;

  @include media($small) {
    display: block;
  }

  @include media($medium) {
    display: block;
  }

  @include media($large) {
    display: block;
  }
}

@mixin desktop-hide {
  display: block;

  @include media($small) {
    display: block;
  }

  @include media($medium) {
    display: none;
  }

  @include media($large) {
    display: none;
  }
}

@mixin mobile-hide {
  @include clearfix;
  display: none;

  @include media($small) {
    display: none;
  }

  @include media($medium) {
    display: block;
  }

  @include media($large) {
    display: block;
  }
}

      
    

Layouts

@mixin features-layout

We created the following mixins for layouts that we use in different ways across projects. For example, the @mixin features-layout creates a standard single column story layout with additional white space on larger views.

      
// Features-Layout
// ---------------
// To add white-space around prose for feature projects
@mixin features-layout ($bp) {
  @include span-columns(12);
  @include media($bp) {
    @include span-columns(10 of 12);
    @include shift(1);
  }
}
      
    

@mixin list-grid() & @mixin div-grid()

You can also create a grid using lists or divs. If your grid needs a a single breakpoint, use @mixin list-grid() or @mixin div-grid(), which allow you to define the $breakpoint, $total-column-width and $number-of-items in your grid.

      
@mixin list-grid ($bp, $col-width, $number-li) {
  // Creates a grid for list items at single breakpoint
  // $bp = breakpoint
  // $col-width = the number of span-columns in your grid
  // $number-li = the number of list items

  ul {
    @include span-columns($col-width);
    @include pad(0);

    li {
      @include span-columns($col-width of $col-width);
      @include media($bp) {
        @include span-columns($col-width / $number-li of $col-width);
        @include omega($number-li+n);
      }
    }
  }
}

@mixin div-grid ($bp, $col-width, $number-div) {
  // Create a div grid with single breakpoint
  // $bp = breakpoint
  // $col-width = the number of span-columns in your grid
  // $number-div = the number of divs

  @include media($bp) {
    div {
      @include span-columns($col-width / $number-div of $col-width);
      @include omega($number-div+n);
    }
  }
}
      
    

Typography

Typography styles can be found in helpers/_typography.scss. Georgia is our $base-serif font, and Helvetica Neue is our $base-sans-serif.

Font-Sizes

The $base font-size is 16px. In addition, there are six preset font-sizes assigned to the variables $xxl, $xl, $l, $m, $s, $xs. Those sizes correspond to the number of HTML header elements, but <h1>-<h6> do not have any assigned font-sizes. For flexibility, we've created a series of font-size classes that can be assigned to any element and %placeholders that can be extended to additional classes. For example, you may add the class .font-xxl to an <h1> element, @extend %font-xxl to all <h1> elements, or create a new class, .project-header with @extend %font-xxl.

This is a class .font-xxl

This is a class .font-xl

This is a class .font-l

This is a class .font-m

This is a class .font-s
This is a class .font-xs

The @mixin font-size() is called on the preset font-size variables on each of the .font-size classes, but it can be called on any class to set a particular module's font-size.

The @mixin font-size() takes three arguments — $font-size-number, $pct and $bp. The $pct and $bp variables allow you to change the font-size by a percentage at a certain breakpoint — but you don't have to use these variables! We've included a default $pct of 1, and a default $bp, $default-mobile, in the @font-size mixin. The font-size extensions and classes (i.e. %font-m and .font-m, etc.), include a $pct of .9 to reduce the font-size by 10% on small screens (i.e. the $default-mobile breakpoint). Change the size of your screen to preview how this mixin works.

      
      // Typography
      // ==========

      // Base Typography Variables
      $base-sans-serif: $helvetica;
      $base-serif: $georgia;

      // Font Sizes
      $base: 16;
      $xxl: 36;
      $xl: 28;
      $l: 22;
      $m: 18;
      $s: 14;
      $xs: 12;

      @mixin font-size($f, $pct:1, $bp:$default-mobile) {
        font-size: $f+px; // for IE8
        font-size: $f/$base+rem;

        @if $pct != 1 {
          @include media($bp) {
            font-size: $f*$pct+px; // for IE8
            font-size: $f*$pct/$base+rem;
          }
        }

      }

      .sans {
        font-family: $base-sans-serif;
      }

      .serif {
        font-family: $base-serif;
      }

      // These classes can be applied to any element
      // to set the font-size.
      %font-xxl,
      .font-xxl {
        @include font-size($xxl, .9);
      }

      %font-xl,
      .font-xl {
        @include font-size($xl, .9);
      }

      %font-l,
      .font-l {
        @include font-size($l, .9);
      }

      %font-m,
      .font-m {
        @include font-size($m, .9);
      }

      %font-base,
      .font-base {
        @include font-size($base, .9);
      }

      %font-s,
      .font-s {
        @include font-size($s, .9);
      }

      %font-xs,
      .font-xs {
        @include font-size($xs, .9);
      }

      
    

Base Elements

The only place that base HTML elements should be given styles is in the helpers/_base.scss file. Few typography styles are assigned directly to HTML elements. All elements in the <body> have the following styles — $base-sans-serif, font-size 16px, and line-height: 1 — unless otherwise specified.

Headers, paragraphs, links and unordered lists are the only HTML elements with additional typography styles. To normalize any bold settings that a browser may apply, we've applied font-weight: 400 to <h1>-<h6>.

The base <ul> element does not include padding, margins or a list-style, so that unordered lists can be used to create other types of components. For a bulleted or carated list, include the classes .bullet and .carat, respectively.

We've also included styles to normalize padding on <aside> and <blockquote> elements.

And we've styled <hr>, and added a .yellow to apply $tribune-yellow.

Example Header

This is a paragraph with a fake link.

  • This is a regular list of items.
  • Styles have been normalized, so you can use it as a building block.
  • If you want pretty styles/margins/etc. use .bullet.
  • This list has class .bullet
  • Because we like our bullet points dotted.
  • This list has class .carat
  • Cause it's cute.


      

        <header>
          <h3 class="font-m">Example Header</h3>
        </header>
        <p>This is a paragraph with a <a href="">fake link</a>.</p>
        <ul>
          <li>This is a regular list.</li>
          <li>Styles have been normalized, so you can use it as a building block.</li>
        </ul>
        <ul class="bullet">
          <li>This list has class .bullet</li>
          <li>Because we like our bullet points dotted.</li>
        </ul>
        <ul class="carat">
          <li>This list has class .carat</li>
          <li>Cause it's cute.</li>
        </ul<
        <hr>
		<hr class="yellow">
      
    
      
/* Base Theme for HTML elements */

body {
  background-color: $white;
  font-family: $base-sans-serif;
  line-height: 1;
}

a {
  color: $href-teal;
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
}

aside,
blockquote {
  margin: 0 0 1em;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-weight: 400;
  margin: 0 0 .5em;
}

q,
p {
  @include font-size($base);
  font-family: $base-serif;
  font-weight: 400;
  line-height: 1.4;
  margin: 0 0 1em;
}

ul {
  list-style: none;
  padding: 0;

  &.bullet,
  &.carat {
    font-family: $base-sans-serif;
    font-weight: 400;
    padding: 0 1em;

    li {
      margin-bottom: .5em;

      &:last-child {
        margin-bottom: 1em;
      }
    }

  }

  &.bullet {
    list-style: disc;
  }

  &.carat {

    li {
      &:before {
        content: '\203A';
        font-family: $base-sans-serif;
        margin: 0 .5em 0 -1em;
        padding: 0;
      }
    }
  }

}

figure {
  margin: 0;

  img {
    width: 100%;
  }
}

hr {
  background-color: $line-gray;
  border: 0 none;
  height: 2px;
  margin-bottom: 1em;

  &.thin {
    height: 1px;
  }

  &.yellow {
    background-color: $tribune-yellow;
  }
}


.container {
  @include clearfix;
}

      
    

Select & Input

The themes .prose and .graphic include an extension of %forms, base styles for <select> and <input> fields found in the _base.scss file. Unlike other base styles, these are not applied directly to <select> and <input> elements. You can @extend %forms to any class, as we've extended these styles extended .prose or .graphic.

      
      <select class="full-width">
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
      </select>

      <form action="demo_form.asp">
        <input type="text" name="FirstName" placeholder="Hello world!">
        <input type="submit" value="Submit" class="button">
      </form>      
      
    
      
%forms {
  form,
  select {
    display: inline-block;
    &.full-width {
      width: 100%;
    }
  }

  select,
  input[type="text"],
  input[type="radio"],
  input[type="email"],
  input[type="number"] {
    @extend %font-base;
    background: transparent;
    border: 1px solid $line-gray;
    display: inline-block;
    font-family: $base-sans-serif;
    font-weight: 400;
    margin-bottom: .5em;
    min-height: 2em;
  }

  option,
  input[type="text"],
  input[type="radio"],
  input[type="email"],
  input[type="number"] {
    padding: .5em .25em;
  }

  input[type="submit"],
  input[type="button"] {
    @include btn($tribune-yellow);
  }
}
      
    

Prose

Basic prose styles, and the follow components, can be found in theme/_prose.scss.

To add our basic paragraph styles to a class, @extend %prose. You can also wrap elements in .prose to apply the basic paragraph styles.

      
/* Base Prose Theme */
%prose {
  @extend %font-base;
  color: $bodytext-black;
  display: block;
  font-family: $base-serif;
  font-weight: 400;
  line-height: 1.4;
  text-align: left;
}

.prose {
  @extend %prose;
  @include clearfix;

  ul {
    @extend %font-s;
    font-family: $base-sans-serif;
    font-weight: 600;
    list-style: disc;
    padding: 0 1em;
  }

  li {
    margin-bottom: .5em;

    &:last-child {
      margin-bottom: 1em;
    }
  }

}
      
    

Headlines, Bylines

Use the classes .headline and .byline for basic headlines.

Cat Saves Planet from Apocolypse, Dies in Action

      
      <header>
        <h1 class="headline">Cat Saves Planet from Apocolypse, Dies in Action</h1>
        <p class="byline">By <a href="http://www.texastribune.org/about/staff/alexa-ura/">Captain Planet</a> | July 0, 2084</p>
      </header>
      
    
      
.headline {
  @extend %font-l;
  font-family: $base-sans-serif;
  font-weight: 600;
  margin: 1.25em 0 .6em;
}

.byline {
  @extend %font-s;
  font-family: $base-sans-serif;
  margin-bottom: 1em;

  a {
    font-weight: 800;
  }
}

      
    

Captions

Captions for photos and other media elements are styled using .caption. Images within .prose will fill 100% of the available width, unless otherwise specified.

This is a picture of a kitten inside a figure.prose.
      
      <figure class="prose">
        <img src="http://placekitten.com/g/500/300">
        <figcaption class="caption">This is a picture of a kitten inside a figure.prose.</figcaption>
      </figure>
      
    
      
%caption,
.caption {
  @extend %font-s;
  color: $text-gray;
  font-family: $base-sans-serif;
  font-weight: 400;
  margin: .25em 0;
}
      
    

Paragraph Headers

That ^ is an example of a .paragraph-header. Notice it will automatically transform the text to uppercase. You can also use these styles on other elements using @extend %paragraph-header.

      
        <h3 class="paragraph-header">Paragraph Headers</h3>
      
    
      
%paragraph-header,
.paragraph-header {
  font-family: $base-sans-serif;
  font-size: .875em;
  font-weight: 700;
  letter-spacing: 1px;
  margin: 0 0 1em;
  text-transform: uppercase;
}
      
    

Explainer Text

Use .explainer-text when you're explaining something, such as how to use the Hospitals Explorer or to define a glossary definition. You can also @extend %explainer-text to another class.

      
      <p class="explainer-text">Text goes here</p>
      
    
      
%explainer-text,
.explainer-text {
  background: $explainer-gray;
  color: $bodytext-black;
  font-family: $base-sans-serif;
  font-weight: 300;
  line-height: 1.3;
  padding: 1em;
  margin-bottom: 1em;
}
      
    

Prose Blocks

Add .prose-block to elements that you want to highlight inside your prose with a yellow border on top and bottom, such as block-quotes or embedded lists. This class does not need to be wrapped inside .prose. In most cases, you'll put this type of content in an <aside>.

Note: To normalize <aside> and <blockquote> margins across browsers, we've included "margin: 0 0 1em" in helpers/_base.scss.

      
      <aside class="prose-block">
        <h3 class="paragraph-header">Example list</h3>
        <ul class="bullet">
          <li>One</li>
          <li>Two</li>
          <li>Three</li>
        </ul>
      </aside>
      
    
      
.prose-block {
  border-color: $tribune-yellow;
  border-style: solid;
  border-width: 1px 0;
  margin-bottom: 1em;
  padding: 1em 0 0;
  position: relative;
}
      
    

Block Quotes

Use a .blockquote for the text of a block quote, and .blockquote-source for the attribution. You can include the block quote in an <aside> or <blockquote> — whichever you prefer. We recommending using <q> for your quotes to ensure the browser applies curled double-quotations. If you use a <p class="blockquote">, remember to include HTML ASCII characters for curled double quotations on either end of the text.

Below are two examples of block quotes. The first is an <aside class="prose-block"> with &lt;q class="blockquote">. The second is a <blockquote class="prose-block"> with <p class="blockquote">:

“You know what’s awesome? Cats. Cats are awesome.”

— Becca Aaronson, cat enthusiast

      
      // Example 1
      <aside class="prose-block">
        <q class="blockquote">You know what’s awesome? Cats. Cats are awesome.</q>
        <p class="blockquote-source">— Becca Aaronson, cat enthusiast</p>
      </aside>

      // Example 2
      <blockquote class="prose-block">
        <p class="blockquote">“You know what’s awesome? Cats. Cats are awesome.”</p>
        <p class="blockquote-source">— Becca Aaronson, cat enthusiast</p>
      </blockquote>
      
    
      
.blockquote {
  @extend %font-m;
  font-family: $base-serif;
  font-style: italic;
  font-weight: 700;
  line-height: 1.2;
  position: relative;
  text-align: left;
}

q.blockquote {
  display: block;
}

.blockquote-source {
  @extend %font-base;
  font-family: $base-sans-serif;
  font-weight: 300;
}
      
    

Buttons

Add the @mixin btn($color) to create any color button with the basic button styles. Button styles are not applied to the <button> tag directly. For standard buttons, use .button, which has @mixin btn($tribune-yellow) included. For a ghost button, add the argument 'ghost': @mixin btn($color, ghost). The class .ghost-button will include a teal ghost button.

      
@mixin btn($color, $type: null) {
  @include clearfix;
  border-radius: 4px;
  cursor: pointer;
  display: inline-block;
  font-family: $base-sans-serif;
  letter-spacing: .03rem;
  margin: 0 0 0.3em;
  text-align: center;
  vertical-align: middle;


  @if $type == ghost {
    background: transparent;
    border: 2px solid $color;
    color: $color;
    padding: .4em .75em .5em;
  } @else {
    background: $color;
    @if $color == $teal {
     color: $white;
    } @else {
      color: $bodytext-black;
    }
    border: 0px;
    padding: .5em .75em .625em;
  }

  &:active,
  &:hover {
    @if $type == ghost {
      background-color: transparentize($color, 0.95);
    } @else {
      background-color: transparentize($color, .3);
    }
  }
}

.button {
  @include btn($tribune-yellow);
}

.ghost-button {
  @include btn($teal, ghost);
}
      
    

Graphic Theme

You can find specific styles for Tribune graphics in theme/_graphic.scss. To use these styles, wrap the class .graphic around your HTML.

Graphic headers have less font-weight.

You can also use a .subhead inside .graphic

And .subtext/%subtext for explainer text related to the graphic.

      
        <div class="graphic">
          <header class="graphic">
            <h1>Graphic headers have less font-weight.</h1>
            <p class="subhead">You can also use a .subhead inside .graphic</p>
          </header>
          <p class="subtext">And .subtext for explainer text related to the graphic.</p>
          <p class="footer">Source/Credit: Add .footer</p>
        </div>
      
    
      
.graphic {
  @include clearfix;
  @extend %forms;
  line-height: 1.4;
  margin: 0 0 1.875em;
  // padding-bottom: 1em;

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    font-weight: 300;
    margin: 0 0 .45em;
  }

  h1 {
    @extend %font-l; // 22px
  }

  // For secondary header lines
  // (typically applied to 

) .subhead { @extend %font-m; font-family: $base-sans-serif; font-weight: 300; margin: 0 0 .5em; } // Explanatory subtext %subtext, .subtext { @extend %font-s; color: $bodytext-black; font-family: $base-sans-serif; font-weight: 300; letter-spacing: .03em; margin: 0 0 .715em; // 10px } .footer { @include clearfix; @extend %font-xs; background-color: $white; color: lighten($bodytext-black, 45%); font-family: $base-sans-serif; margin: .5em 0; text-align: left; ul { list-style-type: none; margin: 0; padding: 0; } } }

Tables

The @mixin responsive-table() has a variety of options to help build the perfect responsive table for your needs. When the table converts to a mobile-view, you can either display the headers as blocks (default) or inline with the cell value (and change the width of the header). You can also choose to hide the first row header and convert the cell value to header styles (default) or show the header.

      
@mixin responsive-table($bp-table:$default-mobile, $hide-first-th:true, $mobile-header-type:block, $mobile-header-width:30%) {
  font-family: $base-sans-serif;
  margin-bottom: 1em;
  width: 100%;

  @include media($bp-table) {
    border-top: 1px solid $line-gray;
    display: block;
    font-size: .875em;
  }

  thead {
    @include media($bp-table) {
      display: none;
    }
  }

  tbody {
    @include media($bp-table) {
      display: block;
    }
  }

  th,
  td {
    &:last-child,
    &.table-prose {
      text-align: left;
    }

    &:last-child,
    &.table-number {
      text-align: right;

      @include media($bp-table) {
        text-align: left;
      }
    }
  }

  th {
    border-bottom: 1px solid $line-gray;
    font-size: .9em;
    font-weight: 800;
    padding: 0 12px 8px;
    text-align: left;
    vertical-align: middle;

    @include media($bp-table) {
      display: block;
    }
  }

  td {
    font-size: .875em;
    padding: 8px 12px;
    text-align: left;

    @include media($bp-table) {
      @include clearfix;
      display: block;
      font-weight: 300;
      padding: 0 12px 8px;
      text-align: left;

      @if attr(data-title) {
        &:before {
          content: attr(data-title) '\A';
          display: block;
          font-weight: 800;
          margin-bottom: .5em;
          white-space: pre-wrap;
        }
      }

      &:first-child {
        padding-top: 1em;
      }

      @if $hide-first-th {

        &:first-child {
          font-size: 1em;
          font-weight: 800;
          padding-top: 8px;
        }

        &[data-title] {
          &:first-child:before {
            content: none;
          }
        }
      }

      @if $mobile-header-type == inline-block {

        &:before {
          float: left;
          display: inline-block;
          margin: 0 1em .25em 0;
          width: $mobile-header-width;
        }
      }

    }
  }

  tr {
    &:nth-child(odd) td {
      background-color: $background-gray;

      &.highlight {
        background-color: none;
        background-color: transparentize($tribune-yellow, .75);
        font-weight: 600;
      }
    }

    @include media($bp-table) {
      display: block;
    }
  }

  // Include .highlight to bring attention an entire row
  // such as the total values or current year
  tr {
    &.highlight {
      background-color: transparentize($tribune-yellow, .75);
      font-weight: 600;

      &:nth-child(odd) td {
        background-color: transparentize($tribune-yellow, .75);
      }
    }

    td {
      padding-top: .5em;
    }

  }

  td {
    &.highlight {
      background-color: transparentize($tribune-yellow, .75);
      font-weight: 600;

      @include media($bp-table) {
        padding-top: 1em;
      }
    }
  }
}
      
    

For optimal use, you may need to include the following attributes in your table HTML:

  • .highlight: Add to <th> or <td> to highlight a row or cell value
  • data-title="Header Name": Add to <td> to designate the "Header Name" text that will appear on mobile views.
  • class="table-prose": Add to <th> or <td> to ensure text aligns left
  • class="table-number": Add to <th> or <td> to ensure numbers align right

Default settings

    
    @mixin responsive-table(
      $bp-table:$default-mobile, 
      $hide-first-th:true, 
      $mobile-header-type:block, 
      $mobile-header-width:30%
    )
    
  

We've included four classes with the primary table settings, which you can preview below. Here's a more thorough description of the @mixin's variables and default settings:

$bp-table: Breakpoint to switch to mobile styles

  • Accepts = media query
  • Default value = $default-mobile

$hide-first-th: Hides data-title/header info for the first <td> and converts cell value to header styles

  • Accepts = Boolean
  • Default = True

$mobile-header-type: Display data-titles inline-block or block

  • Accepts = inline-block or block
  • Default = block

$mobile-header-width: For inline-block data-titles, you can change the width of the header

  • Accepts = Number/Percent for width attribute
  • Default = 30%

.responsive

First childDefaultDefaultProseNumberLast Child
AppleBananaPineappleThis is an example sentence.4,000,000End
RockPaperScissorsThis is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.$2,000End
BlueRedGreenThis is an example sentence.14End
        
          <table class="responsive">
            <thead>
              <tr>
                <th>First child</th>
                <th>Default</th>
                <th>Default</th>
                <th class="table-prose">Prose</th>
                <th class="table-number">Number</th>
                <th>Last Child</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td data-title="Header 1">Apple</td>
                <td data-title="Header 2">Banana</td>
                <td data-title="What if a header title is really, really long?">Pineapple</td>
                <td class="table-prose" data-title="Prose">This is an example sentence.</td>
                <td class="table-number" data-title="Number">4,000,000</td>
                <td data-title="Last child">End</td>
              </tr>
              <tr>
                <td data-title="Header 1">Rock</td>
                <td data-title="Header 2">Paper</td>
                <td>Scissors</td>
                <td class="table-prose" data-title="Prose">This is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.</td>
                <td class="table-number" data-title="Number">$2,000</td>
                <td data-title="Last child">End</td>
              </tr>
              <tr class="highlight">
                <td data-title="Header 1">Blue</td>
                <td data-title="Header 2">Red</td>
                <td>Green</td>
                <td class="table-prose" data-title="Prose">This is an example sentence.</td>
                <td class="table-number" data-title="Number">14</td>
                <td data-title="Last child">End</td>
              </tr>
            </tbody>
          </table>
        
      
        
        // + Transforms first data cell to header on mobile
        // + Display mobile headers as blocks
        table.responsive {
          @include responsive-table();
        }
        
      

.inline

First childDefaultDefaultProseNumberLast Child
AppleBananaPineappleThis is an example sentence.4,000,000End
RockPaperScissorsThis is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.$2,000End
BlueRedGreenThis is an example sentence.14End
        
        <table class="inline">
          <thead>
            <tr>
              <th>First child</th>
              <th>Default</th>
              <th>Default</th>
              <th class="table-prose">Prose</th>
              <th class="table-number">Number</th>
              <th>Last Child</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td data-title="Header 1">Apple</td>
              <td data-title="Header 2">Banana</td>
              <td data-title="What if a header title is really, really long?">Pineapple</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">4,000,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Rock</td>
              <td data-title="Header 2">Paper</td>
              <td data-title="Header 3">Scissors</td>
              <td class="table-prose" data-title="Prose">This is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.</td>
              <td class="table-number" data-title="Number">$2,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Blue</td>
              <td data-title="Header 2">Red</td>
              <td data-title="Header 3">Green</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">14</td>
              <td data-title="Last child">End</td>
            </tr>
          </tbody>
        </table>
        
      
        
        // + Transforms first data cell to header on mobile
        // + Display mobile headers inline, 30% width
        table.inline {
          @include responsive-table($mobile-header-type:inline-block);
        }
        
      

.show-first-th

First childDefaultDefaultProseNumberLast Child
AppleBananaPineappleThis is an example sentence.4,000,000End
RockPaperScissorsThis is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.$2,000End
BlueRedGreenThis is an example sentence.14End
        
        <table class="show-first-th">
          <thead>
            <tr>
              <th>First child</th>
              <th>Default</th>
              <th>Default</th>
              <th class="table-prose">Prose</th>
              <th class="table-number">Number</th>
              <th>Last Child</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td data-title="Header 1">Apple</td>
              <td data-title="Header 2">Banana</td>
              <td data-title="What if a header title is really, really long?">Pineapple</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">4,000,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Rock</td>
              <td data-title="Header 2">Paper</td>
              <td data-title="Header 3">Scissors</td>
              <td class="table-prose" data-title="Prose">This is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.</td>
              <td class="table-number" data-title="Number">$2,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Blue</td>
              <td data-title="Header 2">Red</td>
              <td data-title="Header 3">Green</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">14</td>
              <td data-title="Last child">End</td>
            </tr>
          </tbody>
        </table>
        
      
        
        // + Includes all data-title headers on mobile
        // + Display mobile headers as blocks
        table.show-first-th {
          @include responsive-table($hide-first-th:false);
        }
        
      

.inline-show-first-th

First childDefaultDefaultProseNumberLast Child
AppleBananaPineappleThis is an example sentence.4,000,000End
RockPaperScissorsThis is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.$2,000End
BlueRedGreenThis is an example sentence.14End
        
        <table class="inline-show-first-th">
          <thead>
            <tr>
              <th>First child</th>
              <th>Default</th>
              <th>Default</th>
              <th class="table-prose">Prose</th>
              <th class="table-number">Number</th>
              <th>Last Child</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td data-title="Header 1">Apple</td>
              <td data-title="Header 2" class="highlight">Banana</td>
              <td data-title="What if a header title is really, really long?">Pineapple</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">4,000,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Rock</td>
              <td data-title="Header 2">Paper</td>
              <td data-title="Header 3">Scissors</td>
              <td class="table-prose" data-title="Prose">This is an example sentence. But what if there's a really long, descriptive paragraph. And we need to include lots of space for it, just in case someone wants to read the whole darn thing.</td>
              <td class="table-number" data-title="Number">$2,000</td>
              <td data-title="Last child">End</td>
            </tr>
            <tr>
              <td data-title="Header 1">Blue</td>
              <td data-title="Header 2">Red</td>
              <td data-title="Header 3">Green</td>
              <td class="table-prose" data-title="Prose">This is an example sentence.</td>
              <td class="table-number" data-title="Number">14</td>
              <td data-title="Last child">End</td>
            </tr>
          </tbody>
        </table>
        
      
        
        // + Includes all data-title headers on mobile
        // + Display mobile headers inline, 30% width
        table.inline-show-first-th {
          @include responsive-table($hide-first-th:false, $mobile-header-type:inline-block);
        }