22 Essential CSS Recipes

Hey there! Today we are going to talk about some useful tricks in CSS. Let's begin with...

Blend Modes

Not so far Firefox and Safari started to support blend modes right as Photoshop does. It also works in Chrome and Opera but with flags. See an example:
Blend Mode You can create different styles. Here's a code of what is going above:

.blend {
    background: #fff;
}
.blend img {
    mix-blend-mode: darken; 
}

Try CSS blend modes and filters playground!

Gradient Borders

Novadays you can use gradients even in borders.
Gradients It is rather simple to use, just need to set pseudo-elements with lower z-index:

.box {
  margin: 80px 30px;
  width: 200px;
  height: 200px;
  position: relative;
  background: #fff;
  float: left;
}
.box:before {
      content: '';
      z-index: -1;
      position: absolute;
      width: 220px;
      height: 220px;
      top: -10px;
      left: -10px;
      background-image: linear-gradient(90deg, yellow, gold);
}

All examples you can find here. Also there is approach with background-clip and background-origin. Someday in the bright future border-image property will be supported by all browsers and solution for this will look as follow:

.box {
    border-image: linear-gradient(to bottom, #000000 0%, #FFFFFF 100%); 
    border-image-slice: 1; /* set internal offset */
}

Transition for z-index

You may didn't know but z-index supports transitions too! It doesn't change it's value on each step so you think that it doesn't have a transition. But it does!
Z-transitions Here's a great example.

currentColor

We can use it to detect the current color so we don't have to define it lots of times.

It can be useful when working with SVG icons which change their color depending on their parents. Usually we do it as follows:

.button {
  color: black;
}
.button:hover {
  color: red;
}
.button:active {
  color: green;
}

.button svg {
  fill: black;
}
.button:hover svg {
  fill: red;
}
.button:active svg {
  fill: green;
}

but let's do it with currentColor:

svg {  
  fill: currentColor;
}

.button {
  color: black;
  border: 1px solid currentColor;
}
.button:hover {
  color: red;
}
.button:active {
  color: green;
}

Another code with pseudoelements:

a {  
  color: #000;
}
a:hover {  
  color: #333;
}
a:active {  
  color: #666;
}

a:after,  
a:hover:after,  
a:active:after {  
  background: currentColor;
  ...
}

Object Fit

Do you remember this moment when you wanted to set background-size for image because it will solve a lot of problems? Now you can use object-fit which is supported by webkit and will be added to Firefox soon.

.image__contain {
  object-fit: contain; 
} 
.image__fill {
  object-fit: fill; 
}
.image__cover {
  object-fit: cover; 
}
.image__scale-down {
  object-fit: scale-down;
}

Object-fit Example.

Checkbox and Radio Buttons Styles

Let's make a checkbox style that won't use any images:

 <input type="checkbox" id="check" name="check" />
 <label for="check">Checkbox</label>
input[type=checkbox] {display: none;}

input[type=checkbox] + label:before {  
    content: "";
    border: 1px solid #000;
    font-size: 11px;    
    line-height: 10px;
    margin: 0 5px 0 0;
    height: 10px;
    width: 10px;
    text-align: center;
    vertical-align: middle;
}

input[type=checkbox]:checked + label:before {  
    content: "\2713";
}

Checkbox

As you can see, it works with pseudo-elements and pseudo-selector :checked (IE9+). In the code above we hide original checkbox and show ours instead. When checked, we show a Unicode character using the content.

Note that the Unicode character in CSS differs from that in HTML. In CSS the number is specified in hexadecimal notation with trailing slash at the beginning, while in HTML it's decimal and will look like &#10003;.

Let's add some animation to our checkbox:

input[type=checkbox] + label:before {  
    content: "\2713";
    color: transparent;
    transition: color ease .3s;
}
input[type=checkbox]:checked + label:before {  
    color: #000;
}

and radio button:

input[type=radio] + label:before {  
    content: "\26AB";
    border: 1px solid #000;
    border-radius: 50%;
    font-size: 0;    
    transition: font-size ease .3s;
}
input[type=radio]:checked + label:before {  
    font-size: 10px;    
}

Radio

You can find the full Unicode list here and play with the code.

Counters in CSS

Not everyone know that counters can be made with CSS:

<ol class="list">  
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ol>  
.list {
    counter-reset: i; //reset conunter
}
.list > li {
    counter-increment: i; //counter ID
}
.list li:after {
    content: "[" counter(i) "]"; //print the result
}

We define a random ID in counter-reset property and it's first value (0 by default). You can set another number in counter-increment. It will define the step of your counter.

For example counter-increment: i 2 will displays only even numbers.

Advanced CSS Counters

You can also count those checkboxes which were selected by user:

<div class="languages">  
  <input id="c" type="checkbox"><label for="c">C</label>
  <input id="C++" type="checkbox"><label for="C++">C++</label>
  <input id="C#" type="checkbox"><label for="C#">C#</label>
  <input id="Java" type="checkbox"><label for="Java">Java</label>
  <input id="JavaScript" type="checkbox"><label for="JavaScript">JavaScript</label>
  <input id="PHP" type="checkbox"><label for="PHP">PHP</label>
  <input id="Python" type="checkbox"><label for="Python">Python</label>
  <input id="Ruby" type="checkbox"><label for="Ruby">Ruby</label>
</div>  
<p class="total">  
  Total selected:
</p>  
.languages {
  counter-reset: characters;
}
input:checked {  
  counter-increment: characters;
}
.total:after {
  content: counter(characters);
} 

Here we increment the value of input:checked and print it, example here.

Languages

You can also build a small calculator:

<div class="numbers">  
  <input id="one" type="checkbox"><label for="one">1</label>
  <input id="two" type="checkbox"><label for="two">2</label>
  <input id="three" type="checkbox"><label for="three">3</label>
  <input id="four" type="checkbox"><label for="four">4</label>
  <input id="five" type="checkbox"><label for="five">5</label>
  <input id="one-hundred" type="checkbox"><label for="one-hundred">100</label>
</div>  
<p class="sum">  
  Sum 
</p>  
.numbers {
  counter-reset: sum;
}

#one:checked { counter-increment: sum 1; }
#two:checked { counter-increment: sum 2; }
#three:checked { counter-increment: sum 3; }
#four:checked { counter-increment: sum 4; }
#five:checked { counter-increment: sum 5; }
#one-hundred:checked { counter-increment: sum 100; }

.sum::after {
  content: '= ' counter(sum);
} 

It works the same way. Live demo and article about it.
Calculator

Do your remember how often do you have to use a "hamburger" icon?
Hamburger Icon

There are at least 3 mothods of how to paint it:

1. Shadows

   .shadow-icon {
   position: relative;
   }
   .shadow-icon:after {
     content: "";
     position: absolute;
     left: 0;
     top: -50px;
     height: 100%;
     width: 100%;
     box-shadow: 0 5px 0 #000, 0 15px 0 #fff, 0 25px 0 #000, 0 35px 0 #fff, 0 45px 0 #000;
     }

2. Gradient

.gradient-icon {
    background: linear-gradient(to bottom, #000 0%, #000 20%, transparent 20%, transparent 40%, #000 40%, #000 60%, transparent 60%, transparent 80%, #000 80%, #000 100%);
}

3. UTF-8 You can just paste this standard symbol: ☰ (Unicode: U+2630, HTML: &#9776;). You can adjust it's color or size only so it's not as flexible as other methods.

See the example.

You can also use SVG, icon font or borders with pseudo-elements.

@Supports

There's a new expression in CSS called supports. As you can see, it can inspect whether browser supports needed option. Not all of browser support it, but you still can use it for simple checks:

@supports (display: flex) {
    div { display: flex; }
}

/*You can check prefixes*/
@supports (display: -webkit-flex) or (display: -moz-flex) or (display: flex) {
    section {
        display: -webkit-flex;
        display: -moz-flex;
        display: flex;
        float: none;
    }
}

visibility: visible

How do yout think, what will be if you put visibility: visible block into another one with visibility: hidden?

.hidden {
  visibility: hidden;
}
.hidden .visible {
  visibility: visible;
}

You might think that all will be hidden but parent will hide all excepting it's child. Please look at the demo.

position: sticky

We've discovered a new feature that now you can create "sticky" blocks. They will be working the same as fixed blocks but won't hide another blocks. You'd better see it.
Sticky block Right now only Mozilla and Safari support it but you can still use it this way:

.sticky {
  position: static;
  position: sticky;
  top: 0px;
}

We will get a sticky block in browsers which support it and a regular block in other programs.
It is rather useful for mobile sites where you need to create a movable block which won't substitute others.

New Dimensions

Not so far this world discovered some new ways to describe sizes of different objects. Here are them:

  • vw (viewport width) - one percent of browser window's width.
  • vh (viewport height) - the same but for height.
  • vmin and vmax choose minimal and maximal value between vh and vw.

The interesting thing is that they all are great supported in most of modern browsers so you can freely use them.
Why do we need them? That's because they make all dimensions simpler. You don't have to specify percentage of parent's element size and any other stuff. Just have a look:

.some-text {
    font-size: 100vh;
    line-height: 100vh;
}

vh and vw

Or you can put a beautiful popup at the center of the screen:

.blackSquare {
    background: black;
    position: fixed;
    height: 50vh;
    width: 50vw;
    left: 25vw;
    top: 25vh;
}

That seems to be cool solution. See this example at Codepen.

Also there are some negative facts about using this feature:

  • IE9 should be told to use vm instead of vmin.
  • iOS7 may have some bugs with vh.
  • vmax is not fully supported yet.

Text Decorations

We can change text selection color with a couple lines of code:

*::selection {
    color: #fff;
    background: #000;
}
*::-moz-selection {    
    /*Only Firefox still needs a prefix*/
    color: #fff;
    background: #000;
}

You can define not only a color for selection, but shadows and backgrounds too.

Block Scroll on Touch Devices

If you have some blocks with inner scroll in them then you have to add not only overflow: scroll / auto but this line also:

-webkit-overflow-scrolling: touch;

The thing is that mobile browser sometimes don't work with overflow: scroll property correctly and scroll all the page instead of the needed block. -webkit-overflow-scrolling fix this issue. You can see it by adding this to your own project.

Using Hardware Acceleration

Sometimes your animation can to slow down client's computer. You can use acceleration for special block in order to prevent this event:

.block {
    transform: translateZ(0);
}

In statics you won't notice any difference, but browsers will understands that the element should be treated as three-dimensional and will enable acceleration. Until there are no normal support of specifically designed for this property will-change, this method is quite descend.

Unicode Classes

Now you can set classes names as Unicode symbols:

.❤ {
    ...
}
.☢ {
    ...
}
.☭ {
    ...
}
.★ {
    ...
}
.☯ {
    ...
}

But it's a silly joke. Try not to use it in big projects as UTF-8 may not be supported on every computer.

Vertical Margines in Percents

It's a fact that vertical indents are calculated from parent's width but not height. Let's create two blocks:

<div class="parent">  
    <div class="child"></div>
</div>  
.parent {
    height: 400px;
    width: 200px;
}
.child {
    height: 50%;
    padding-top: 25%;
    padding-bottom: 25%;
    width: 100%;
}

In theory, should fill it's parent by height but see what we get instead:
Vertical Margines in Percents

You should keep in mind that percents are calculated from the parent's width.

Margins in Firefox Buttons

Firefox has it's own method of buttons margins calculations. That seems to be strange but it manually adds some of them by it's own.

Firefox margins

It can be fixed this way:

button::-moz-focus-inner,  
input[type="reset"]::-moz-focus-inner,  
input[type="button"]::-moz-focus-inner,  
input[type="submit"]::-moz-focus-inner {  
    border: none;
    padding:0;
}

Color + Border = Border-Color

Not everyone know that, by defining text color for any object, you also define it's border color:

input[type="text"] {  
    color: red;
    border: 1px solid;
}

Border Color

Bonus for Oldies

If you still have to support IE7 or something like that then you can define their hacks with a smile like this:

body {  
    :) background: pink;
}

It is pretty, isn't it?


I apologize for any typos. If you notice a problem - please write in PM.

Thank you all for your attention.