A collection of tips to help take your CSS skills pro.

  1. Use :not() to Apply/Unapply Borders on Navigation
  2. Add Line-Height to body
  3. Vertically-Center Anything
  4. Comma-Separated Lists
  5. Select Items Using Negative nth-child
  6. Use SVG for Icons
  7. Use the “Lobotomized Owl” Selector
  8. Use max-height for Pure CSS Sliders
  9. Inherit box-sizing
  10. Equal Width Table Cells
  11. Get Rid of Margin Hacks With Flexbox
  12. Use Attribute Selectors with Empty Links
  13. Style “Default” Links

Use :not() to Apply/Unapply Borders on Navigation

Instead of putting on the border…

/* add border */
.nav li {
  border-right: 1px solid #666;
}

…and then taking it off the last element…

/* remove border */
.nav li:last-child {
  border-right: none;
}

…use the :not() pseudo-class to only apply to the elements you want:

.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.

Add Line-Height to body

You don’t need to add line-height to each <p>, <h*>, et al. separately. Instead, add it to body:

body {
  line-height: 1;
}

This way textual elements can inherit from body easily.

Vertically-Center Anything

No, it’s not black magic, you really can center elements vertically:

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.

Comma-Separated Lists

Make list items look like a real, comma-separated list:

ul > li:not(:last-child)::after {
  content: ",";
}

Use the :not() pseudo-class so no comma is added to the last item.

Select Items Using Negative 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 items 1 through 3 and display them */
li:not(:nth-child(-n+3)) {
  display: none;
}

Well that was pretty easy.

Use SVG for Icons

There’s no reason not to use SVG for icons:

.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:

.no-svg .icon-only:after {
  content: attr(aria-label);
}

Use the “Lobotomized Owl” Selector

It may have a strange name but using the universal selector (*) with the adjacent sibling selector (+) can provide a powerful CSS capability:

* + * {
  margin-top: 1.5em;
}

In this example, all elements in the flow of the document that precede other elements will receive margin-top: 1.5em.

For more on the “lobotomized owl” selector, read Heydon Pickering’s post on A List Apart.

Use 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.

Inherit box-sizing

Let box-sizing be inherited from html:

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.

Equal Width Table Cells

Tables can be a pain to work with so try using table-layout: fixed to keep cells at equal width:

.calendar {
  table-layout: fixed;
}

Pain-free table layouts.

Get Rid of Margin Hacks With Flexbox

When working with column gutters you can get rid of nth-, first-, and last-child hacks by using flexbox’s space-between property:

.list {
  display: flex;
  justify-content: space-between;
}

.list .person {
  flex-basis: 23%;
}

Now column gutters always appear evenly-spaced.

Use Attribute Selectors with Empty Links

Display links when the <a> element has no text value but the href attribute has a link:

a[href^="http"]:empty::before {
  content: attr(href);
}

That’s pretty convenient.

Style “Default” Links

Add a style for “default” links:

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.