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.
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.
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 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.
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.
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.
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.
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">
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.
<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>
Captions for photos and other media elements are styled using .caption. Images within .prose will fill 100% of the available width, unless otherwise specified.
<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>
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.
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.
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.
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 <q class="blockquote">. The second is a <blockquote class="prose-block"> with <p class="blockquote">:
“You know what’s awesome? Cats. Cats are awesome.”
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.
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.
Source/Credit: Add .footer
<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>
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.
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 child
Default
Default
Prose
Number
Last Child
Apple
Banana
Pineapple
This is an example sentence.
4,000,000
End
Rock
Paper
Scissors
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.
$2,000
End
Blue
Red
Green
This is an example sentence.
14
End
<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 child
Default
Default
Prose
Number
Last Child
Apple
Banana
Pineapple
This is an example sentence.
4,000,000
End
Rock
Paper
Scissors
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.
$2,000
End
Blue
Red
Green
This is an example sentence.
14
End
<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 child
Default
Default
Prose
Number
Last Child
Apple
Banana
Pineapple
This is an example sentence.
4,000,000
End
Rock
Paper
Scissors
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.
$2,000
End
Blue
Red
Green
This is an example sentence.
14
End
<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 child
Default
Default
Prose
Number
Last Child
Apple
Banana
Pineapple
This is an example sentence.
4,000,000
End
Rock
Paper
Scissors
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.
$2,000
End
Blue
Red
Green
This is an example sentence.
14
End
<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);
}