A collection of tips to help take your CSS skills pro.
For other great lists check out @sindresorhus 's curated list of awesome lists .
-
Use
:not()
to Apply/Unapply Borders on Navigation -
Add
line-height
tobody
- Vertically-Center Anything
- Comma-Separated Lists
-
Select Items Using Negative
nth-child
- Use SVG for Icons
- Use the "Lobotomized Owl" Selector
-
Use
max-height
for Pure CSS Sliders -
Inherit
box-sizing
- Equal-Width Table Cells
- Get Rid of Margin Hacks With Flexbox
- Use Attribute Selectors with Empty Links
- Style "Default" Links
- Consistent Vertical Rhythm
- Intrinsic Ratio Boxes
- Style Broken Images
-
Use
rem
for Global Sizing; Useem
for Local Sizing - Hide Autoplay Videos That Aren't Muted
-
Use
:root
for Flexible Type -
Set
font-size
on Form Elements for a Better Mobile Experience
Instead of putting on the border...
css
/* add border */
.nav li {
border-right: 1px solid #666;
}
...and then taking it off the last element...
css
/* remove border */
.nav li:last-child {
border-right: none;
}
...use the
:not()
pseudo-class to only apply to the elements you want:
css
.nav li:not(:last-child) {
border-right: 1px solid #666;
}
Sure, you can use
.nav li + li
or even
.nav li:first-child ~ li
, but with
:not()
the intent is very clear and the CSS selector defines the border the way a human would describe it.
You don't need to add
line-height
to each
,
,
et al
. separately. Instead, add it to
body
:
css
body {
line-height: 1.5;
}
This way textual elements can inherit from
body
easily.
No, it's not black magic, you really can center elements vertically:
```css html, body { height: 100%; margin: 0; }
body { -webkit-align-items: center; -ms-flex-align: center; align-items: center; display: -webkit-flex; display: flex; } ```
Want to center something else? Vertically, horizontally...anything, anytime, anywhere? CSS-Tricks has a nice write-up on doing all of that.
Note: Watch for some buggy behavior with flexbox in IE11.
Make list items look like a real, comma-separated list:
css
ul > li:not(:last-child)::after {
content: ",";
}
Use the
:not()
pseudo-class so no comma is added to the last item.
Note: This tip may not be ideal for accessibility, specifically screen readers. And copy/paste from the browser doesn't work with CSS-generated content. Proceed with caution.
Use negative
nth-child
in CSS to select items 1 through n.
```css li { display: none; }
/* select items 1 through 3 and display them */ li:nth-child(-n+3) { display: block; } ```
Or, since you've already learned a little about
using
:not()
, try:
css
/* select items 1 through 3 and display them */
li:not(:nth-child(-n+3)) {
display: none;
}
Well that was pretty easy.
There's no reason not to use SVG for icons:
css
.logo {
background: url("logo.svg");
}
SVG scales well for all resolution types and is supported in all browsers back to IE9 . So ditch your .png, .jpg, or .gif-jif-whatev files.
Note: If you have SVG icon-only buttons for sighted users and the SVG fails to load, this will help maintain accessibility:
css
.no-svg .icon-only:after {
content: attr(aria-label);
}
It may have a strange name but using the universal selector (
*
) with the adjacent sibling selector (
+
) can provide a powerful CSS capability:
css
* + * {
margin-top: 1.5em;
}
In this example, all elements in the flow of the document that follow other elements will receive
margin-top: 1.5em
.
For more on the "lobotomized owl" selector, read Heydon Pickering's post on A List Apart .
Implement CSS-only sliders using
max-height
with overflow hidden:
```css .slider { max-height: 200px; overflow-y: hidden; width: 300px; }
.slider:hover { max-height: 600px; overflow-y: scroll; } ```
The element expands to the
max-height
value on hover and the slider displays as a result of the overflow.
Let
box-sizing
be inherited from
html
:
```css html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; } ```
This makes it easier to change
box-sizing
in plugins or other components that leverage other behavior.
Tables can be a pain to work with so try using
table-layout: fixed
to keep cells at equal width:
css
.calendar {
table-layout: fixed;
}
Pain-free table layouts.
When working with column gutters you can get rid of
nth-
,
first-
, and
last-child
hacks by using flexbox's
space-between
property:
```css .list { display: flex; justify-content: space-between; }
.list .person { flex-basis: 23%; } ```
Now column gutters always appear evenly-spaced.
Display links when the
element has no text value but the
href
attribute has a link:
css
a[href^="http"]:empty::before {
content: attr(href);
}
That's pretty convenient.
Add a style for "default" links:
css
a[href]:not([class]) {
color: #008000;
text-decoration: underline;
}
Now links that are inserted via a CMS, which don't usually have a
class
attribute, will have a distinction without generically affecting the cascade.
Use a universal selector (
*
) within an element to create a consistent vertical rhythm:
css
.intro > * {
margin-bottom: 1.25rem;
}
Consistent vertical rhythm provides a visual aesthetic that makes content far more readable.
To create a box with an intrinsic ratio, all you need to do is apply top or bottom padding to a div:
```css .container { height: 0; padding-bottom: 20%; position: relative; }
.container div { border: 2px dashed #ddd; height: 100%; left: 0; position: absolute; top: 0; width: 100%; } ```
Using 20% for padding makes the height of the box equal to 20% of its width. No matter the width of the viewport, the child div will keep its aspect ratio (100% / 20% = 5:1).
Make broken images more aesthetically-pleasing with a little bit of CSS:
css
img {
display: block;
font-family: Helvetica, Arial, sans-serif;
font-weight: 300;
height: auto;
line-height: 2;
position: relative;
text-align: center;
width: 100%;
}
Now add pseudo-elements rules to display a user message and URL reference of the broken image:
```css img:before { content: "We're sorry, the image below is broken :("; display: block; margin-bottom: 10px; }
img:after { content: "(url: " attr(src) ")"; display: block; font-size: 12px; } ```
Learn more about styling for this pattern in Ire Aderinokun 's original post .
After setting the base font size at the root (
html { font-size: 16px; }
), set the font size for textual elements to
em
:
```css h2 { font-size: 2em; }
p { font-size: 1em; } ```
Then set the font-size for modules to
rem
:
```css article { font-size: 1.25rem; }
aside .module { font-size: .9rem; } ```
Now each module becomes compartmentalized and easier to style, more maintainable, and flexible.
This is a great trick for a custom user stylesheet. Avoid overloading a user with sound from a video that autoplays when the page is loaded. If the sound isn't muted, don't show the video:
css
video[autoplay]:not([muted]) {
display: none;
}
Once again, we're taking advantage of using the
:not()
pseudo-class.
The type font size in a responsive layout should be able to adjust with each viewport. You can calculate the font size based on the viewport height and width using
:root
:
css
:root {
font-size: calc(1vw + 1vh + .5vmin);
}
Now you can utilize the
root em
unit based on the value calculated by
:root
:
css
body {
font: 1em/1.6 sans-serif;
}
To avoid mobile browsers (iOS Safari,
et al
.) from zooming in on HTML form elements when a
drop-down is tapped, add
font-size
to the selector rule:
css
input[type="text"],
input[type="number"],
select,
textarea {
font-size: 16px;
}
:dancer:
back to table of contents
Support
Current versions of Chrome, Firefox, Safari, Opera, Edge, and IE11.
Translations
Español
Français
Italiano
日本語
Português do Brasil
Русский
简体中文