Pro-tip: Press space bar to progress and it won't skip any slides
For Practical Peoples
Prologue
Part 1
1%
33.333%
150%
.parent {
border-color: gray;
border-style: dashed;
}
.box {
width: 50%;
background: deepskyblue;
}
.box
em
1em = Calculated font-size of current element
1em
1.25em
3em
.box {
width: 2em;
background: deepskyblue;
}
.box-2 {
font-size: 2em;
width: 2em;
background: palegreen;
}
.box
.box-2
.box {
/* font-size: 16px; (default) */
width: 2em; /* 2em = 16px * 2 = 32px */
background: deepskyblue;
}
.box-2 {
font-size: 2em; /* 2em = 16px * 2 = 32px */
/* The 32px font-size will then change what
2em on the width means */
width: 2em; /* 2em = 32px * 2 = 64px */
background: palegreen;
}
rem
1rem = Calculated font-size of html element
1rem
1.25rem
3rem
.box {
width: 2rem;
background: deepskyblue;
}
.box-2 {
font-size: 2rem;
width: 2rem;
background: palegreen;
}
.box
.box-2
ex and chBased on the font that renders
1ex
1.25ex
15ex
1ex = Calculated width of a lower-case x
1ch
1.25ch
15ch
1ch = Calculated width of the number 0
.box {
font-family: monospace;
width: 25ch;
background: deepskyblue;
}
.box-2 {
font-family: sans-serif;
width: 25ch;
background: palegreen;
}
100vw
25vw
100vh
25vh
mm millimetercm centimeterin inchpt pointpc picaWhen size should be proportionate to the unit's basis
Sized with em
Sized with px
A fallback, if you can't/shouldn't use a relative unit*.
* Most devs and teams I've known use pixels by default, while that has drawbacks, it's not "bad".
Special styles for specific circumstances
@media /* Conditions */ {
/* CSS Rules */
}
@media screen { /* Computer Display CSS Rules */ }
@media print { /* Print CSS Rules */ }
Fun fact: speech, braille, embossed (braille printers), tty (like command line), tv also exist.
@media (min-width: 768px) {
/* CSS Rules */
}
/* OR the newest Comparison syntax */
@media (width >= 768px) { /* CSS Rules */ }
@media (min-width: 48em) and (min-height: 30em) {
/* CSS Rules */
}
@media (400px <= width <= 600px) {
/* Styles for viewports between 400px and 600px. */
}
@media Best Practices@media queries
Write min-width and min-height,
not max-width or max-height
.box {
/* Mobile CSS */
}
@media (min-width: 48em) {
.box {
/* Decent size screen styles */
}
}
@media (min-width: 62em) {
.box {
/* Huge screen styles */
}
}
/* Widget Styles */
.widget { }
@media (min-width: 768px) {
.widget { }
}
/* Doo Dad Styles */
.doo-dad { }
@media (min-width: 768px) {
.doo-dad { }
}
@media (min-width: 768px) and screen {
/* Is screen necessary, do we want to exclude print? */
.widget { }
}
@media (min-width: 1024px) and (min-height: 768px) {
/* Is height necessary, should 750px tall screens be excluded? */
.widget { }
}
That means asking questions like:
Test from 350px - 1600px wide.
This screenshot is faked
Basics and terminology
Element surrounding the grid.
Direct child element of a grid container
Any line in the grid
.grid-container {
display: grid;
grid-template-columns: 25% 50% 25%;
}
Grid code examples stolen/modified from GridByExample.com, from Rachel Andrew
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: -3;
grid-column-end: -1;
grid-row-start: -2;
grid-row-end: -1;
grid-column-start: 1;
grid-column-end: -1;
.my-header {
grid-column: 1 / -1;
}
.my-content {
grid-column: 1 / span 2;
}
.my-sidebar {
grid-row: 2;
grid-column: 3;
}
grid-template-areasName regions in your grid.
.grid-container {
display: grid;
grid-template-columns: 25% 50% 25%;
grid-template-areas:
"header header header"
"content content sidebar"
"footer footer footer";
}
grid-areaSet location of grid items to a grid region.
.my-header { grid-area: header; }
.my-content { grid-area: content;}
.my-sidebar { grid-area: sidebar;}
.my-footer { grid-area: footer; }
.grid-container {
display: grid;
grid-template-columns: 50% 50%;
grid-template-areas:
'header header'
'content content'
'sidebar footer';
}
frDistributes free space in a grid track
grid-template-row: 1fr 50% 1fr;
1fr 1fr /* 50% 50% (Maybe) */
1fr 2fr 1fr /* 25% 50% 25% (Maybe) */
25% 1fr 1fr /* 25% 37.5% 37.5% (Maybe) */
minmax()
display: grid;
gap: 10px;
grid-template-columns:
minmax(200px, 1fr) 200px 200px;
repeat(number, size)
display: grid;
gap: 10px;
grid-template-columns: repeat(4, 100px);
grid-template-rows: repeat(3, auto);
auto-fit and auto-fill
grid-template-columns: repeat(auto-fit, 150px)
grid-template-columns: repeat(auto-fill, 150px)
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
You may assume this would have a good result:
.wrapper {
display: grid;
grid-template-columns: 25% 25% 25% 25%;
gap: 10px;
}
.wrapper {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
}
Fix the equal width grid with gutters yourself:
codepen.io/pen/RvBzrV
Try more CSSGridGarden.com
Or explore GridByExample.com
Basics and terminology
Element enclosing everything
Direct child of flex container
The axis the flex items are laid out on (row/column).
The opposite axis of the main (column/row)
The beginning of the main axis is where items start from, end is the opposite side.
The beginning of the cross axis will be top if flex is horizontal, left if it's vertical
.flex-container {
display: flex; /* All you need */
/* flex-direction: row; (Default) */
/* flex-wrap: nowrap; (Default) */
}
flex-wrap.flex-container {
display: flex;
/* flex-direction: row; (Default) */
flex-wrap: wrap;
}
flex-direction.flex-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
Examples of flex-direction
align-items valuesalign-items: center;align-items: baseline;All of the previous properties applied to flex containers, these are for flex items.
orderChanges the visual order of the elements on the page.
.flex-item-3 {
order: 1;
}
order is calculated like weight in Drupal, heavier goes to the end, lighter goes to the top.
.flex-item-1 { /* Not set */ }
.flex-item-2 { order: -999; }
.flex-item-3 { order: 100; }
.flex-item-4 { order: 10; }
.flex-item-5 { /* Not set */ }
flex-growDistributes extra space to items that have a value
.flex-item-3 { flex-grow: 2; }
.flex-item-4 { flex-grow: 1; }
flex-shrinkWhen there isn't enough space items will shrink to fit
.flex-item-3 { flex-shrink: 2; }
.flex-item-4 { flex-shrink: 1; }
flex-basisSets initial size of flex item on the main axis, before flex-grow or flex-shrink are applied.
.flex-item-3 { flex-basis: 4em; }
.flex-item-4 { flex-basis: 2em; }
margin and flex items💖auto will use left over space to push as far as it can
.flex-item-3 {
margin: auto;
}
Try styling a menu for an up and coming (fake) industrialist super-power:
codepen.io/pen/rPrERx
Hint: Having A Complete Guide to Flexbox from CSS-Tricks.com open in another browser may come in handy!
| Key Quality | Grid | Flexbox |
|---|---|---|
| Layout Specialty | 2d layout | 1d layout |
| Prefers respecting | Layout (content conforms) |
Content (layout flexes) |
gapalign-[items/content]align-selfjustify-[items/content]gapWith 1 value, it applies to rows and columns, 2 values set row, then column.
Formerly known as: column-gap/row-gap/grid-gap/grid-row-gap/grid-column-gap
.flex-container {
display: flex;
/* gap: 5px 10px; /* Sets row to 5px and column gap to 10px */
gap: 5px; /* Sets row and column gap to 5px */
}
justify-contentHow extra space is distributed along the main axis
grid is always horizontal..flex-container {
display: flex;
justify-content: center;
}
justify-content valuesjustify-content: flex-start;justify-content: flex-end;justify-content valuesjustify-content: space-between;justify-content: space-around;justify-content: space-evenly;align-itemsHow extra space is distributed along the cross axis
.flex-container {
display: flex;
align-items: center;
}
align-items valuesalign-items: stretch; /* (Default) */align-items: flex-start;align-items: flex-end;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum nibh diam, et rhoncus nulla interdum vitae. Suspendisse ac quam justo. In ut enim faucibus, aliquet velit a, rhoncus mauris. Ut pharetra magna ac euismod gravida. Aenean fringilla ex sit amet est condimentum, fermentum dapibus diam finibus. Donec id tortor turpis. Morbi semper turpis quis posuere sagittis. Suspendisse ac pulvinar magna, a hendrerit arcu. Aenean dictum nunc sit amet libero fringilla, vel vulputate risus auctor. Vestibulum interdum vulputate nibh et sodales. Donec lorem nisi, mattis quis tempus sed, finibus at velit. Curabitur pharetra libero eget felis ornare finibus. Vivamus eget sollicitudin risus, eu lobortis est. Duis sed lectus a purus luctus fermentum. Duis consequat gravida ex, id pellentesque turpis finibus eu.
.column-container {
column-count: 3;
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum nibh diam, et rhoncus nulla interdum vitae. Suspendisse ac quam justo. In ut enim faucibus, aliquet velit a, rhoncus mauris. Ut pharetra magna ac euismod gravida. Aenean fringilla ex sit amet est condimentum, fermentum dapibus diam finibus. Donec id tortor turpis. Morbi semper turpis quis posuere sagittis. Suspendisse ac pulvinar magna, a hendrerit arcu. Aenean dictum nunc sit amet libero fringilla, vel vulputate risus auctor. Vestibulum interdum vulputate nibh et sodales. Donec lorem nisi, mattis quis tempus sed, finibus at velit. Curabitur pharetra libero eget felis ornare finibus. Vivamus eget sollicitudin risus, eu lobortis est. Duis sed lectus a purus luctus fermentum. Duis consequat gravida ex, id pellentesque turpis finibus eu.
column-width.column-container {
column-width: 9em;
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum nibh diam, et rhoncus nulla interdum vitae. Suspendisse ac quam justo. In ut enim faucibus, aliquet velit a, rhoncus mauris. Ut pharetra magna ac euismod gravida. Aenean fringilla ex sit amet est condimentum, fermentum dapibus diam finibus. Donec id tortor turpis. Morbi semper turpis quis posuere sagittis. Suspendisse ac pulvinar magna, a hendrerit arcu. Aenean dictum nunc sit amet libero fringilla, vel vulputate risus auctor. Vestibulum interdum vulputate nibh et sodales. Donec lorem nisi, mattis quis tempus sed, finibus at velit. Curabitur pharetra libero eget felis ornare finibus. Vivamus eget sollicitudin risus, eu lobortis est. Duis sed lectus a purus luctus fermentum. Duis consequat gravida ex, id pellentesque turpis finibus eu.
gap.column-container {
column-count: 3;
gap: 2em;
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum nibh diam, et rhoncus nulla interdum vitae. Suspendisse ac quam justo. In ut enim faucibus, aliquet velit a, rhoncus mauris. Ut pharetra magna ac euismod gravida. Aenean fringilla ex sit amet est condimentum, fermentum dapibus diam finibus. Donec id tortor turpis. Morbi semper turpis quis posuere sagittis. Suspendisse ac pulvinar magna, a hendrerit arcu. Aenean dictum nunc sit amet libero fringilla, vel vulputate risus auctor. Vestibulum interdum vulputate nibh et sodales. Donec lorem nisi, mattis quis tempus sed, finibus at velit. Curabitur pharetra libero eget felis ornare finibus. Vivamus eget sollicitudin risus, eu lobortis est. Duis sed lectus a purus luctus fermentum. Duis consequat gravida ex, id pellentesque turpis finibus eu.
break-inside.column-children {
break-inside: avoid;
}
The most basic and oldest layout method on the web.
<div> has one default style, display: blockwidth, heightmargin, paddingborder<strong>, <em>, <span>)
-or- the effects of cat grumpiness


positionVery useful, and often misused.
top, bottom, left, rightChange the location of "positioned" elements
z-indexDetermines vertical layering of "positioned" elements
position: static;Position's default value, these elements are not "positioned" so associated styles are ignored.
.element {
position: static;
top: 100px; /* Ignored, because position: static */
left: 50px; /* Static isn't considered "positioned" */
float: left;
}
position: relative;Update the element from where it would rendered.
.element {
position: relative;
top: 25px;
left: 50px;
float: left;
}
position: absolute;Update the element based on positioning of a "positioned" parent element
.element {
position: absolute;
top: 0;
left: 0;
float: left;
}
position: fixed;Positions element to the window and element doesn't move when page scrolls.
.element {
position: fixed;
top: 100px;
left: 50px;
}
position: sticky;Element will stick to defined position when page scrolls
(Not ready for prime time yet)
.element {
position: sticky;
top: 100px;
left: 50px;
}
positionposition: absolute.element {
position: absolute;
top: 0;
left: 0;
}
z-indexSome guidelines
Think in this order as a general rule:
position: absolute;position: fixed;marginposition: relative; if top/right/bottom/left are settransform/rotate/translate/skew/scale
Best meaning for the client, budget, or your sanity.
aspect-ratio.blue-box {
width: 25%;
aspect-ratio: 2 / 1;
}
margin and flex items❓margin does not collapse inside of a flex container
.flex-item-3 {
margin-left: 2em;
margin-right: 2em;
}
.flex-item-4 { margin-left: 2em; }
margin and grid itemsmargin pushes on the grid area instead of adjacent elements.
/* Assuming left to right, top to bottom language, like English is: */
width/height ~ inline-size/block-size
margin-left/margin-right ~ margin-inline-start/margin-inline-end
margin-inline ~ margin-left + margin-right
border-top/border-bottom ~ border-block-start/border-block-end
border-block ~ border-top + border-bottom
top/bottom ~ inset-block-start/inset-block-end
left/right ~ inset-inline-start/inset-inline-end
/* Follows same rules as margin/padding values */
inset ~ top right bottom left
transformtransform: translate(x, y);.element {
transform: translate(50px, 25px);
}
transform: translate(x);.element {
transform: translate(50px);
}
transform: scale(x);.element {
transform: scale(2);
}
transform: scale(x, y);.element {
transform: scale(2, 0.5);
}
transform: rotate(deg);.element {
transform: rotate(45deg);
}
transform: skew(deg, deg);.element {
transform: skew(45deg, 15deg);
}
transform-origin: x, y;.blue-element,
.red-element {
transform: rotate(45deg);
/* transform-origin: center center; Default */
}
.red-element {
transform-origin: left top;
}
Order matters!
.blue-element {
transform: translate(200px) rotate(45deg);
}
.red-element {
transform: rotate(45deg) translate(200px);
}
transition.element {
transition: transform 1s;
}
.element:hover {
transform: translate(50px, 25px);
}
.element {
transition: transform 1s, background 3s;
}
.element:hover {
transform: translate(50px, 25px);
background: rgba(200, 0, 0, 0.6);
}
Image from: Jotform - How to Use CSS Animations Like a Pro
.blue-element { transition: transform 1s linear; }
.red-element { transition: transform 1s ease-in; }
.yellow-element { transition: transform 1s ease-out; }
.blue-element { transition-delay: 0; }
.red-element { transition-delay: 1s; }
.yellow-element { transition-delay: 2s; }
animation@keyframes slide-in {
0% {
transform: translate(-15em);
opacity: 0;
}
100% {
transform: translate(0);
opacity: 1;
}
}
@keyframes slide-in { ... }
.element {
animation-name: slide-in;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes slide-all-over {
0% {
transform: translate(-15em);
opacity: 0;
}
33% {
transform: translate(-10em, -5em);
}
66% {
transform: translate(-5em, 5em);
}
100% {
transform: translate(0);
opacity: 1;
}
}
If the desired animation can be done with transform, it should be.
.element {
animation-name: slide-in;
animation-duration: 2s;
animation-iteration-count: infinite;
}
/* If they prefer reduced motion, you can remove animation completely,
Or go with something that has minimal movement */
@media (prefers-reduced-motion: reduce) {
.element {
animation: none;
}
}
cubic-bezier()Make your own animation timing!
Now with web site helper!:before and :after(aka pseudo-content)
<span>Bare minimum is a selector, before or after, and the content attribute (which can be an empty string).
.element:before {
content: '';
}
This creates an empty invisible element.
.clearfix:after {
content: '';
display: table;
clear: both;
}
So long as it isn't necessary for the content to be understood.
.email-address:before {
content: 'Contact me at ';
}
someone@something.com
[data-label]:before {
content: attr(data-label);
display: inline-block;
margin-right: 0.5em;
padding: 0.25em 0.5em;
background: rgb(225, 200, 0);
color: rgb(100, 50, 0);
}
@media print {
main a[href]:after {
content: " (" attr(href) ") ";
}
}
I stole this idea from CSS Tricks
There are a lot of tools, Web AIM contrast checker is an easy one
Accessibility browser extensions like WAVE and Axe Devtools will test for this, but they have false positives sometimes
:focus selector when adding :hover selector*
.button:hover,
.button:focus {
background: #121399;
}
*In general, form elements are an exception, e.g. text input, select, checkbox, radio, etc. Having a separate hover vs focus is often preferred with them.
display: none;
visibility: hidden;.element-invisible .sr-only
text-indent: -9999em; aka the Phark technique 🤓
(and better mousing!)
*This is less applicable to links in the flow of text and content that isn't near more clickable elements
Photo by Wade Austin Ellis on Unsplash


body.html.page-node-X
#header
#header-wrapper h2,
body.html.page-node-X
#header
#header-wrapper
#block-views-view-name-block-1
> .view-view-name
> .view-content
> .views-row
> .row-inner
> .views-field-title,
body.html.page-node-X
#header
#header-wrapper
#block-views-view-name-block-1
> .view-view-name
.attachment
.view-heading,
#block-views-view-name-block-1
> .view-view-name
.attachment
body.html.page-node-X
#header
#header-wrapper
.view-heading,
body.html.page-node-X
#header
#header-wrapper
#block-views-view-name-block-1
> .view-view-name
.attachment
.view-view-name
.views-row
.views-field-title,
#block-views-view-name-block-1
> .view-view-name
.attachment
.view-view-name
.views-row
body.html.page-node-X
#header
#header-wrapper
.views-field-title {
display: block;
text-align: center;
line-height: 1.3em;
padding-top: 140px
}
tagname
Type/Tag (0, 0, 1)
.class-name
Class (0, 1, 0)
#id-name
ID (1, 0, 0)
*
Universal (0, 0, 0)
[attribute]
Attribute (0, 1, 0)
<div attribute-name="value"><div>
[attribute-name] [attribute-name='value'] [attribute-name*='lu'] [attribute-name^='val']
All of these are a specificity of (0, 1, 0)
>
Direct descendant (0, 0, 0)
~
General sibling (0, 0, 0)
+
Adjacent Sibling (0, 0, 0)
:hover, :focus
(0, 1, 0)
:first-child, :last-child
(0, 1, 0)
:empty
(0, 1, 0)
:checked
(0, 1, 0)
:nth-child Pseudo-Classes:nth-child()
(0, 1, 0)
:nth-of-type()
(0, 1, 0)
:nth-last-child()
(0, 1, 0)
.article h4 a
.main-menu > li a
.bio-photo ~ .bio-name
.js .carousel .slide
#main .article a
(1, 1, 1)
#page #main a
(2, 0, 1)
h4.sidebar-title a
(0, 1, 2)
#main .article a
(1, 1, 1)
.article a
(0, 1, 1)
#page #main a
(2, 0, 1)
[id="main"] a
(0, 1, 1)
h4.sidebar-title a
(0, 1, 2)
.sidebar-title a
(0, 1, 1)
<article class="node node-news node-published node-not-promoted node-not-sticky clearfix" id="node-news-2" about="/page-url" typeof="foaf:Document">
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even" property="content:encoded">
<p>Hello World!</p>
</div>
</div>
</div>
</article>
.node-news .field-name-bodyThan this:
.node .field
Explicit classes are meant to target very specific elements, e.g. .widget__photo--captioned
Utility classes are meant to apply very specific styles, e.g. .text-align-center
Consider prefixing utility classes, e.g. .u-text-align-center
e.g. Lullabot.com Example
gr- for giantrabbit.com) you know where it came from.sidebar .col-lg-3 {
text-align: right;
/* .col-lg-3 is intended for layout, not text treatment :( */
}
!important unless you're overriding inline styles or another important that you can't remove..main-header .header-logoheader.main-header.widget__title--featured[id=”id-name”].my-widget[class][class]nth-child Tricksaka CSS variables
:root {
/* Setting a custom property */
--my-cool-var: #c00001;
}
.my-element {
/* Use the custom property with no fallback */
background-color: var(--my-cool-var);
/* Use it with a fallback, in case it isn't set */
background-color: var(--my-cool-var, #c00);
}
Technically it does, but in the real world it's low value and high cost.
See:
Performance Impact of CSS Selectors - Steve stevesouders
@importwill-change to clue in browser to animationsfont-display to prevent a web font from blocking render