Future of CSS
GET READY FOR THE
@guilh
Guil Hernandez
@guilh
Variables
Filters
Blending
shapes
colors
selectors
CSS Variables
(Custom Properties)
CSS variables hold references to values you reuse throughout your stylesheet
--property-name: value;
CSS Variables
:root {
--color-primary: #278da4;
--color-secondary: #b13c69;
}
var()
CSS Variables
:root {
--color-primary: #278da4;
--color-secondary: #b13c69;
}
.headline {
color: var(--color-secondary);
}
.btn {
background-color: var(--color-primary);
}
var( )
CSS Variables
:root {
--color-bg: #3acec2;
--color-bg-light: #009fe1;
}
header {
background-image: linear-gradient( var(--color-bg-light),
var(--color-bg) );
}
var( )
CSS Variables
:root {
--color-bg: #3acec2;
--color-bg-light: #009fe1;
--gradient: var(--color-bg-light),
var(--color-bg);
}
header {
background-image: linear-gradient( var(--gradient) );
}
var( )
CSS Variables
:root {
/* Fonts */
--font-stack-primary: 'Raleway', sans-serif;
--font-stack-secondary: 'Bree Serif', serif;
/* Layout */
--max-width: 1000px;
--gutter: 10px;
}
CSS variables do things preprocessor variables can’t
Preprocessor Variables
- Static
- Do not run in browser
- Not aware of the DOM structure
CSS Variables
- Aware of the DOM structure
- Dynamic
- Update at runtime
CSS Variables
@media (min-width: 576px) {
:root {
--gutter: 2em;
}
}
@media (min-width: 768px) {
:root {
--gutter: 3em;
}
}
Media queries
CSS Variables
:root {
--gutter: 0.5em;
}
.headline {
margin-bottom: var(--gutter);
}
.col + .col {
margin-left: var(--gutter);
}
Media queries
CSS Variables
:root {
--gutter: 0.5em;
}
...
@media (min-width: 576px) {
:root {
--gutter: 2em;
}
}
@media (min-width: 768px) {
:root {
--gutter: 3em;
}
}
Media queries
CSS Variables
Media queries
CSS variables inherit, cascade and can be scoped to selectors
CSS Variables
.btn {
...
background-color: var(--button-bg);
}
.btn.callout {
--button-bg: #1de9b6;
}
.btn.info {
--button-bg: #0097bf;
}
Selector scope
CSS Variables
Selector scope
CSS Variables
Assigned inline
Style elements based on where they appear in the DOM
CSS Variables
.banner .btn { ... }
.card .btn { ... }
.modal > .btn { ... }
Inheritance
CSS Variables
.btn {
font-size: var(--btn-font-size);
color: var(--btn-color);
background-color: var(--btn-bg);
...
}
Inheritance
CSS Variables
.banner {
--btn-font-size: 1.2em;
--btn-bg: #1de9b6;
}
.card {
--btn-font-size: 1.1em;
--btn-bg: #db35ed;
}
.modal {
--btn-font-size: 0.85em;
--btn-bg: #0097bf;
}
Inheritance
CSS Variables
Inheritance
CSS Variables
:root {
--gutter: 2;
}
.img-featured {
margin-bottom: calc(var(--gutter) * 10px); /* 20px */
}
.headline {
margin-bottom: calc(var(--gutter) * 1em); /* 2em */
}
Calculations
Communicate between JavaScript and CSS, using CSS variables
CSS Variables
Update with JS
getPropertyValue()
setProperty()
CSS Variables
.ball {
background-color: var(--ball-bg, tomato);
transform: translate( calc( var(--pos-x) * 1px),
calc( var(--pos-y) * 1px) );
}
Update with JS
CSS Variables
// Select element
let ball = document.querySelector('.ball');
// Update custom property values
ball.style.setProperty('--pos-x', e.clientX);
ball.style.setProperty('--pos-y', e.clientY);
ball.style.setProperty('--ball-bg', randomHex());
Update with JS
Where CSS variables do not work
CSS Variables
/* selectors */
var(--button-info) {
color: white;
background-color: tomato;
}
/* property names */
.card {
var(--color-primary): #278da4;
}
Invalid variables
CSS Variables
/* media query expressions */
@media (min-width: var(--break-med)) {
...
}
/* creating length values */
.box {
margin: var(--gutter)em;
}
/* this is valid */
.box {
margin: calc(var(--gutter) * 1em);
}
Invalid variables
Compositing & Blending
Compositing
The combining of a graphic element with its backdrop
Blending
Calculates the mixing of colors wherever an element and a backdrop overlap
background-blend-mode
mix-blend-mode
Blending
header {
background: linear-gradient(#009fe1, #3acec2),
url('bg.jpg') no-repeat;
background-blend-mode: multiply;
}
background-blend-mode
mix-blend-mode
Blending
.img-mix {
width: 650px;
mix-blend-mode: lighten;
}
mix-blend-mode
.img-featured {
...
background-color: #f8f295;
}
.img-featured img {
...
mix-blend-mode: multiply;
}
<div class="img-featured">
<img src="featured.jpg" alt="vr">
</div>
mix-blend-mode
Blending
svg {
background-color: #f8f295;
}
svg image {
mix-blend-mode: multiply;
}
<svg viewBox="0 0 600 600">
<image xlink:href="featured.jpg" width="600" height="600">
<svg>
mix-blend-mode
Blending
mix-blend-mode
Blending
backdrop-filter
(Filter Effects Level 2)
blur()
brightness()
contrast()
drop-shadow()
grayscale()
hue-rotate()
invert()
opacity()
sepia()
saturate()
Backdrop Filter
.filter {
...
backdrop-filter: invert(100%) blur(2px);
}
header {
background-image: url(...);
}
Backdrop filter
Backdrop filter
Backdrop filter
CSS shapes
Use geometric shapes as CSS values and flow text around those shapes
CSS Shapes
.img-shape {
width: 190px;
border-radius: 50%;
float: left;
shape-outside: circle();
}
shape-outside
CSS Shapes
.img-shape {
border-radius: 50%;
float: left;
shape-outside: circle();
}
shape-outside
CSS Shapes
.img-shape {
border-radius: 50%;
float: left;
shape-outside: border-box;
}
shape-outside
CSS Shapes
.img-shape {
border-radius: 50%;
float: left;
shape-outside: border-box;
shape-margin: 20px;
}
shape-margin
polygon()
CSS Shapes
.triangle {
width: 200px;
height: 600px;
float: left;
shape-outside: polygon(0 0, 0 200px, 300px 600px);
}
shape-outside
CSS Shapes
shape-outside
CSS Shapes
shape-outside
CSS Shapes Editor
CSS Clip Paths
Partially (or fully) hide portions of an HTML element
Clip Paths
.img-moon {
float: left;
clip-path: circle(115px at 50% 50.3%);
}
Clip Paths
Clip Paths
.img-moon {
float: left;
clip-path: circle(115px at 50% 50.3%);
shape-outside: circle(115px at 50% 50.3%);
shape-margin: 25px;
}
Clip Paths
Clip Paths
<svg width="0" height="0">
<clipPath id="clipPolygon">
<polygon points="..."></polygon>
</clipPath>
</svg>
h1 {
...
clip-path: url('#clipPolygon');
}
SVG clip-path
Clip Paths
header {
...
clip-path: polygon(0 0, 100% 0, 100% 89%, 0% 100%);
}
Clip Paths
Color Values
8 Digit Hex Notation
#RRGGBBAA
Transparent Color Value
#2D5A7400
Opaque Color Value
#2D5A74FF
Hex Notation
.icon {
/* 50% alpha */
color: #278DA480;
}
#RRGGBBAA
Hex Notation
.icon {
/* 80% alpha */
color: #278DA4CC;
}
#RRGGBBAA
Hex Notation
.icon {
/* 20% alpha */
color: #278DA433;
}
#RRGGBBAA
Hex Notation
Browser support
color-mod()
Modifying Colors
.box {
background-color: color-mod(
#278da4 /* modified color */
hue(+ 5deg)
lightness(+ 15%)
alpha(75%)
);
}
color-mod
a:hover {
color: color-mod( #278da4 lightness(+ 20%) );
}
Modifying Colors
a:hover {
color: color-mod( #278da4 lightness(- 5%) );
}
Modifying Colors
.box {
background-color: color-mod(
#278da4
hue(+ 5deg)
lightness(+ 15%)
alpha(75%)
);
}
Modifying Colors
:root {
--base: crimson;
--base-dark: color-mod(var(--base) lightness(- 30%));
--base-light: color-mod(var(--base) lightness(+ 25%));
--complement: color-mod(var(--base) hue(+ 180deg));
--complement-light: color-mod(var(--complement) lightness(+ 10%));
}
Modifying Colors
--base: cornflowerblue;
--base: hotpink;
--base: crimson;
Selectors
Level 4
Functional Pseudo-class
:matches
Selectors Level 4
:matches(.card, .modal, form) .btn {
font-size: 1.25em;
}
/*
.card .btn,
.modal .btn,
form .btn { ... }
*/
:matches
Selectors Level 4
a:matches(:hover, :focus, :active, :visited) {
color: tomato;
}
/*
a:hover,
a:focus,
a:active
a:visited {...}
*/
:matches
Pseudo-elements and combinators
(+, >, ~) are invalid arguments
Selectors Level 4
:matches(img, p, form) + p {
margin-top: 0;
}
/*
img + p,
p + p,
form + p {...}
*/
:matches
:matches
Selectors Level 4
Optionality Pseudo-classes
:required
|
:optional
Validity Pseudo-classes
:valid
| :invalid
.email:valid {
border-color: forestgreen;
}
.email:invalid {
border-color: firebrick;
}
<input class="email" type="email" required>
:valid | :invalid
Selectors Level 4
.email:valid {
border-color: forestgreen;
}
.email:valid + .icn::before {
content: '😃';
}
<input class="email" type="email" required>
<span class="icn"></span>
:valid | :invalid
Selectors Level 4
:valid | :invalid
Selectors Level 4
.email:focus:invalid {
border-color: firebrick;
}
.email:focus + .icn::before {
content: '😳';
}
.email:valid {
border-color: forestgreen;
}
.email:valid + .icn::before {
content: '😃';
}
:valid | :invalid
Selectors Level 4
:valid | :invalid
Selectors Level 4
Feature Queries
@supports
= Native Feature Detection
Feature Queries
.main-content {
display: flex;
flex-wrap: wrap;
}
.card {
flex: 1 280px;
margin: 10px;
}
@supports (display: grid) { /* 🔥 Grid Layout 🔥 */
.main-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
grid-gap: 20px;
}
.card {
margin: 0;
}
}
@supports
Feature Queries
@supports (writing-mode: vertical-rl) and (display:grid) {
main {
display: grid;
grid-template-columns: 100px 1fr;
grid-column-gap: 15px;
}
h1 {
justify-self: start;
writing-mode: vertical-rl;
}
}
@supports
Feature Queries
@supports
Browser support
Feature Queries
Browser Support
Thank you!👋
Guil Hernandez
@guilh
Get Ready for the Future of CSS – CSSConfEU
By guilh
Get Ready for the Future of CSS – CSSConfEU
Slides for CSSConfEU talks. Covers the latest CSS features, including: CSS variables, blending, backdrop filters, shapes and colors, @supports and more.
- 1,994