A collection of tips to help take your CSS skills pro.
For other great lists check out [@sindresorhus](https://github.com/sindresorhus/)’s curated list of awesome lists.
box-sizing
unset
Instead of Resetting All Properties
:not()
to Apply/Unapply Borders on Navigation
line-height
to body
:focus
for Form Elements
nth-child
max-height
for Pure CSS Sliders
rem
for Global Sizing; Use em
for Local
Sizing
:root
for Flexible Type
font-size
on Form Elements for a Better Mobile
Experience
display: none
on Line Breaks Used as Spacing
CSS resets help enforce style consistency across different browsers with a clean slate for styling elements. You can use a CSS reset library like Normalize, et al., or you can use a more simplified reset approach:
Now elements will be stripped of margins and padding, and
box-sizing
lets you manage layouts with the CSS box model.
Note: If you follow the
Inherit box-sizing
tip
below you might opt to not include the box-sizing
property in
your CSS reset.
box-sizing
Let box-sizing
be inherited from html
:
This makes it easier to change box-sizing
in plugins or other
components that leverage other behavior.
unset
Instead of Resetting All Properties
When resetting an element’s properties, it’s not necessary to reset each individual property:
button {
background: none;
border: none;
color: inherit;
font: inherit;
outline: none;
padding: 0;
}
You can specify all of an element’s properties using the
all
shorthand. Setting the value to
unset
changes an element’s properties to their initial
values:
Note: the all
and
unset
shorthand isn’t supported in IE11.
:not()
to Apply/Unapply Borders on Navigation
Instead of putting on the border…
…and then taking it off the last element…
…use the :not()
pseudo-class to only apply to the elements
you want:
Here, the CSS selector is read as a human would describe it.
You can check if a font is installed locally before fetching it remotely, which is a good performance tip, too.
@font-face {
font-family: "Dank Mono";
src:
/* Full name */
local("Dank Mono"),
/* Postscript name */
local("Dank Mono"),
/* Otherwise, download it! */
url("//...a.server/fonts/DankMono.woff");
}
code {
font-family: "Dank Mono", system-ui-monospace;
}
H/T to Adam Argyle for sharing this protip and demo.
line-height
to body
You don’t need to add line-height
to each
<p>
, <h*>
, et al.
separately. Instead, add it to body
:
This way textual elements can inherit from body
easily.
:focus
for Form Elements
Sighted keyboard users rely on focus to determine where keyboard events go in the page. Make focus for form elements stand out and consistent then a browser’s default implementation:
a:focus,
button:focus,
input:focus,
select:focus,
textarea:focus {
box-shadow: none;
outline: #000 dotted 2px;
outline-offset: .05em;
}
No, it’s not black magic, you really can center elements vertically. You can do this with flexbox…
html,
body {
height: 100%;
margin: 0;
}
body {
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-flex;
display: flex;
}
…and also with CSS Grid:
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:
Use the :not()
pseudo-class and no comma will be 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.
nth-child
Use negative nth-child
in CSS to select items 1 through n.
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:
/* select all items except the first 3 and display them */
li:not(:nth-child(-n+3)) {
display: block;
}
There’s no reason not to use SVG for icons:
SVG scales well for all resolution types and is supported in all browsers back to IE9. 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:
It may have a strange name but using the universal selector
(*
) with the adjacent sibling selector (+
) can
provide a powerful CSS capability:
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.
max-height
for Pure CSS Sliders
Implement CSS-only sliders using max-height
with overflow
hidden:
.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.
Tables can be a pain to work with. Try using
table-layout: fixed
to keep cells at equal width:
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:
Now column gutters always appear evenly-spaced.
Display links when the <a>
element has no text value
but the href
attribute has a link:
That’s pretty convenient.
Add a style for “default” links:
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.
To create a box with an intrinsic ratio, all you need to do is apply top or bottom padding to a div:
.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:
img {
display: block;
font-family: 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:
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.
rem
for Global Sizing; Use em
for Local
Sizing
After setting the base font size at the root (html { font-size: 100%; }
), set the font size for textual elements to em
:
Then set the font-size for modules to rem
:
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:
Once again, we’re taking advantage of using the
:not()
pseudo-class.
:root
for Flexible Type
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
:
Now you can utilize the root em
unit based on the value
calculated by :root
:
font-size
on Form Elements for a Better Mobile Experience
To avoid mobile browsers (iOS Safari, et al.) from zooming in on
HTML form elements when a <select>
drop-down is tapped,
add font-size
to the selector rule:
:dancer:
Pointer events allow you to specify how the mouse interacts with the element it’s touching. To disable the default pointer event on a button, for instance:
It’s that simple.
display: none
on Line Breaks Used as Spacing
As Harry Roberts pointed out, this can help prevent CMS users from using extra line breaks for spacing:
Current versions of Chrome, Firefox, Safari, Opera, Edge, and IE11.