Teaching CSS to
talk like a designer
Developers & designers often speak different languages
CSS gives us the illusion
it understands design
Taunting us with terms like
`line-height`
& `baseline`
How would you style a 21px heading over 27px line height?
.card-heading {
font-size: 21px;
line-height: 27px;
}
<div class="card">
<h1 class="card-heading">Heading</h1>
</div>
CSS “line-height”
Heading
Typographic line height
Heading
Devs are left to “CSS” until it works
.card-heading {
font-size: 21px;
line-height: 27px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 1px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 2px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 3px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 4px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 4px;
margin-bottom: -1px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 4px;
margin-bottom: -2px;
}
.card-heading {
font-size: 21px;
line-height: 27px;
padding-top: 4px;
margin-bottom: -3px;
}
System left behind is fragile
Thrown away the designer’s thinking
Good design is not an accident
There’s a ‘why’ for everything
Grid systems, type hierarchy, etc
We start with the best intentions
@row-height: 9px;
@column-width: 60px;
@column-gutter: 20px;
@heading-size: 21px;
@heading-line-height: 27px;
.card-heading {
font-size: @heading-size;
line-height: @heading-line-height;
padding-top: 4px;
margin-bottom: -3px;
}
How can we fix this?
CSS “line-height”
Heading
Typographic line height
Heading
Height of the descender*
Heading
*not available in CSS
We have to calculate this manually
@heading-descender-height: 3px;
Font centered to line height
Heading
Half the difference betweeen line-height
and font-size
(27px - 21px) / 2 = 3px
@heading-line-height-offset: 3px;
@heading-offset: (@heading-descender-height + @heading-line-height-offset);
.card-heading {
font-size: @heading-size;
line-height: @heading-line-height;
transform: translateY(@heading-offset);
}
Starting to align with the designer’s intent
Heading
There will be multiple headings
.headingText() {
font-size: @heading-size;
line-height: @heading-line-height;
transform: translateY(@heading-offset);
}
.card-heading {
.headingText();
}
Design and dev can start
talking a common language
.headingText()
…but solution is hardcoded
/* Design principles */
@heading-size: 21px;
@heading-line-height: 27px;
/* Offset hacks */
@heading-descender-height: 3px;
@heading-line-height-offset: 3px;
Designers are still having to translate principles into pixels
Let’s reverse engineer
what’s behind these pixels
Line height is simply a row span
@heading-line-height: 27px;
@row-height: 9px;
.headingText() {
font-size: 21px;
line-height: (3 * @row-height);
transform: translateY(@heading-offset);
}
Where does the font size come from?
@heading-font-size: 21px;
“
The values in the hierarchy are all a scale of a base size, I tend to work off 10px as it scales cleanly
”
@base-font-size: 10px;
.headingText() {
font-size: (2.1 * @base-font-size);
line-height: (3 * @row-height);
transform: translateY(@heading-offset);
}
Extract the principles
/* Design principles */
@base-font-size: 10px;
@row-height: 9px;
@heading-scale: 2.1;
@heading-row-span: 3;
/* Offset hacks */
@heading-descender-height: 3px;
@heading-line-height-offset: 3px;
@heading-offset: (@heading-descender-height + @heading-line-height-offset);
Recap: Heading at 21px over 27px line heightRecap: Heading at 2.1x over 3 grid rows
We’re capturing principles rather than pixels
Implement another hierarchy level?
Add support for subheadings
/* Design principles */
@subheading-scale: 1.8;
@subheading-row-span: 3;
/* Offset hacks */
@subheading-descender-height: ???;
@subheading-line-height-offset: ???;
@subheading-offset: ???;
Express the offset as a scale of the type
CSS can help us here — em
units
Calculate the descender height as scale
Rather than defining for each level
@heading-descender-height: ???;
@subheading-descender-height: ???;
One descender scale per font family
@roboto-descender-scale: 0.15;
/* Offset hacks */
@roboto-descender-scale: 0.15;
@roboto-offset: @roboto-descender-scale * @base-font-size;
@heading-line-height-offset: 3px;
@heading-offset: (@roboto-offset * @heading-scale) + @heading-line-height-offset;
@subheading-line-height-offset: ???;
@subheading-offset: (@roboto-offset * @subheading-scale) + @subheading-line-height-offset;
This is better, but you know…
Do this for every level of the hierarchy?
Translate design principles into CSS rules to align type
.headingText() {
.basekick(
@heading-scale,
@roboto-descender-scale,
@heading-row-span,
@row-height,
@base-font-size
);
}
.card-heading {
font-size: 21px;
line-height: 27px;
transform: translateY(.27935714em);
}
Transform doesn’t push neighbouring elements
Preserves CSS properties for semantic use
Ability to edit design primitives confidently
@heading-scale: 2.1;
@heading-row-span: 3;
@subheading-scale: 1.8;
@subheading-row-span: 3;
Putting it to the test...
.basekick(
@heading-scale,
@roboto-descender-scale,
@heading-row-span,
@row-height,
@base-font-size
);
.basekick(
@heading-scale,
@zapfino-descender-scale,
@heading-row-span,
@row-height,
@base-font-size
);
.basekick(
@heading-scale,
@papyrus-descender-scale,
@heading-row-span,
@row-height,
@base-font-size
);
Design conversations are now centered around common language
2½ years into our journey
Hierarchy has grown
@hero-type-row-span: 5;
@hero-type-scale: 4.2;
@headline-type-row-span: 4;
@headline-type-scale: 2.8;
@heading-type-row-span: 3;
@heading-type-scale: 2.1;
@subheading-type-row-span: 3;
@subheading-type-scale: 1.8;
@standard-type-row-span: 2;
@standard-type-scale: 1.4;
@small-type-row-span: 2;
@small-type-scale: 1.2;
Added responsive variants with ease
@standard-type-row-span: 2;
@standard-type-scale: 1.4;
@standard-type-row-span-mobile: 3;
@standard-type-scale-mobile: 1.8;
System has been adopted in over 10 projects
(across multiple frameworks)
Most developers don’t know basekick exists
CSS is speaking the same
language as our designers
Powerful mindset change for both disciplines
Striving for a common language everywhere
Apply this thinking to our markup
</>
Teach HTML to talk design
Component abstractions can help define a design language
<Text heading>Heading</Text>
Rather than discuss code like this:
<div class="card">
<h1 class="card-heading">Heading</h1>
<p class="card-body">The cards content</p>
</div>
We can more declaratively compose this:
<Card>
<Text heading>My Heading</Text>
<Text>The cards content</Text>
</Card>
Match designer’s intent out of the box
Help find your team’s design language