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