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:
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.
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!
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;
}
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";
}
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
✓
.
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;
}
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.
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.
Menu Icon Without Images
Do your remember how often do you have to use a "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: ☰
). 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.
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
andvmax
choose minimal and maximal value betweenvh
andvw
.
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;
}
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 ofvmin
. - 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:
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.
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;
}
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.