Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ah, tu peux faire ça en CSS maintenant ? (version listing)

Raphael Goetter
November 07, 2022

Ah, tu peux faire ça en CSS maintenant ? (version listing)

CSS a bien évolué.
De simple langage de description à ses débuts, il devient un véritable outil de programmation, embarquant variables, imbrications, conditions et un peu plus chaque jour.
Les évolutions sont parfois si nombreuses qu'il est difficile de tout suivre. Ça tombe bien car c'est justement ce qu'on va faire : un rapide panorama de fonctionnalités modernes mais déjà utilisables en production (variables, sélecteurs, cascade, propriétés logiques, etc.)

Raphael Goetter

November 07, 2022
Tweet

More Decks by Raphael Goetter

Other Decks in Design

Transcript

  1. AH, TU PEUX FAIRE ÇA EN CSS MAINTENANT ? (AVOUE

    QUE TU NE T'ATTENDAIS PAS À TOUT ÇA)
  2. HELLO ! JE SUIS RAPHAËL... raphaël goetter

  3. Depuis 2003 Un forum, des tutos, un service d'emploi Opensource

    et gratuit 30000 visiteurs / jour 50000 membres sur le forum .com Communauté d'apprentissage
  4. .fr Depuis 2006 On fait des sites web performants et

    accessibles On dispense des formations On est une petite équipe de 10 personnes On a un peu l’accent alsacien Agence web, organisme de formation
  5. En fait, il y en a 559 maintenant (source W3C)

    https://twitter.com/housecor/status/1577668059652931586 (il y en avait 50 en CSS1) (source W3C)
  6. LES GRANDES CLASSIQUES 1 connues de tout le monde ?

    LES SÉLÉCTEURS, UNITÉS, VALEURS 2 pas d'effet "wow" mais super utile LES PAS TRÈS CONNUES 3 mais carrément utilisables en prod LES GAME CHANGERS 4 qui changent vraiment la donne LES NOUVEAUTÉS MARQUANTES (ET UTILISABLES) EN CSS
  7. COMPATIBILITÉ NAVIGATEURS https://caniuse.com/css-grid “[email protected]; Toutes les fonctionnalités sont compatibles à

    partir de Edge (sauf exceptions qui seront signalées)
  8. LES GRANDES CLASSIQUES 1 connues de tout le monde ?

  9. LES GRANDS CLASSIQUES 1 position: sticky variables CSS Grid Layout

    @supports clip-path aspect-ratio connues de tout le monde ?
  10. POSITION STICKY position relative et absolute à la fois .header

    { position: sticky; top: 0; } 1 2 3 4 https://elad.medium.com/css-position-sticky-how-it-really-works-54cd01dc2d46
  11. :root { --spacer-md: 20px; } .alert { padding: var(--spacer-md); margin-bottom:

    var(--spacer-md); } 1 2 3 4 5 6 7 On déclare ici la variable dans :root (= tout le document) et on l'associe à une valeur. “Les Custom Properties permettent de rassembler des valeurs courantes afin d'éviter les répétitions On applique la variable sur la ou les propriétés souhaitées VARIABLES CSS en vrai : "Custom Properties"
  12. CUSTOM PROPERTIES OK mais pourquoi c'est mieux que Sass ?

    1. C'est un langage natif 2. C'est une vraie variable et non une valeur statique une fois compilée (Sass) 3. C'est une bénédiction pour les thèmes de couleurs (ou Dark Mode) 4. Les Custom Properties bénéficient de la Cascade CSS 5. Elles sont interrogeables / modifiables à la volée via JavaScript si besoin
  13. CUSTOM PROPERTIES appliquées au Dark Mode :root { --color-one: chocolate;

    --color-two: honeydew; } @media (prefers-color-scheme: dark) { /* redefine dark mode colors here */ :root { --color-one: honeydew; --color-two: chocolate; } } .card { background-color: var(--color-one); color: var(--color-two); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 https://www.stefanjudis.com/today-i-learned/how-to-tell-browsers-that-your-site-supports-color- schemes/
  14. http://kiwi.gg/gridcheat GRID LAYOUT Quand le Positionnement CSS devient 💖

  15. GRID LAYOUT en action .ingrid { display: grid; grid-template-columns: repeat(4,

    1fr); gap: 16px; } 1 2 3 4 5 “Grid Layout est le mode de positionnement parfait pour des gabarits robustes, maintenables et responsive
  16. @SUPPORTS .header { position: relative; } @supports (position: sticky) {

    .header { position: sticky; top: 2rem; } } 1 2 3 4 5 6 7 8 9 Propriétés par défaut “@supports permet de tester le support d'une propriété par le navigateur avant de l'appliquer Propriétés appliquées si "sticky" est reconnu par le navigateur au service de l'amélioration progressive
  17. @SUPPORTS en action (encore) .title { color: #000; } @supports

    (backdrop-filter: initial) { .title { backdrop-filter: blur(10px) brightness(60%); color: #fff; } } 1 2 3 4 5 6 7 8 9
  18. @SUPPORTS détection du "non support" aussi @supports not (display: grid)

    { .ingrid > * { float: left; margin-right: 20px; } } @supports (display: grid) { .ingrid { display: grid; gap: 20px; } } 1 2 3 4 5 6 7 8 9 10 11 12 si le navigateur ne supporte pas Grid Layout si le navigateur supporte Grid Layout
  19. CLIP-PATH pour rogner un élément .box { background: chocolate; color:

    #fff; padding: 2rem; clip-path: polygon(0 0, 100% 8%, 100% 92%, 0% 100%); } 1 2 3 4 5 6 https://bennettfeely.com/clippy/
  20. ASPECT-RATIO pour conserver le ratio d'un élément .video { width:

    100%; aspect-ratio: 16 / 9; } 1 2 3 4 https://css-irl.info/aspect-ratio-is-great/
  21. None
  22. SÉLECTEURS, UNITÉS ET VALEURS 2 pas d'effet "wow" mais super

    utiles
  23. SÉLECTEURS, UNITÉS ET VALEURS 2 clamp, min, max :where() all,

    inherit, initial, unset, revert pas d'effet "wow" mais super utiles
  24. CLAMP() en action h1 { font-size: clamp(2em, 5vw, 50px); }

    1 2 3 Ici la taille de police souhaitée dépend de la largeur de la fenêtre (5vw), la valeur minimum est 2em la valeur maximum est 50px “Clamp renvoie une valeur qui sera comprise entre un minimum et un maximum
  25. MIN() en action body { width: min(1000px, 100%); } 1

    2 3 La largeur de <body> correspond à la plus petite des deux valeurs : Si la taille de la fenêtre est de moins de 1000px, alors il occupera 100% de celle-ci “Min renvoie la valeur la plus petite parmi une liste
  26. MAX() en action :root { --responsive-gap: max(1rem, 2vw); } .hagrid

    { display: grid; gap: var(--responsive-gap); } 1 2 3 4 5 6 7 8 La valeur de la variable dépend de la largeur de fenêtre, mais sera toujours au moins de 1rem “Max renvoie la valeur la plus grande parmi une liste
  27. WHERE() la factorisation de sélecteurs :where(header, main, footer) h1 {

    color: hotpink; } 1 2 3 header h1, main h1, footer h1 { color: hotpink; } 1 2 3 4 5 h1:where(.kiwi, .banane) { color: hotpink; } 1 2 3 h1.kiwi, h1.banane{ color: hotpink; } 1 2 3 4 :where(button,a):where(:hover,:focus) { color: hotpink; } 1 2 3 button:hover, button:focus, a:hover, a:focus { color: hotpink; } 1 2 3 4 5 6 la spécificité (poids) de ce sélecteur est nulle ! 💪
  28. ALL, INHERIT, INITIAL, UNSET, REVERT héritage et réinitialisation .kiwi {

    /* mais... quels seront mes styles ? */ all: inherit; all: initial; all: unset; all: revert; } 1 2 3 4 5 6 7
  29. ALL toutes les propriétés à la fois .parent { display:

    grid; margin: 2rem; color: hotpink; } 1 2 3 4 5 .enfant { all: ... ; } 1 2 3 “La propriété raccourcie "all" permet de contrôler d'un coup toutes les propriétés d'un élément. “Les valeurs possibles sont "inherit", "initial", "unset" et "revert"
  30. INHERIT force l'héritage .parent { display: grid; margin: 2rem; color:

    hotpink; } 1 2 3 4 5 .enfant { all: inherit; } 1 2 3 “"inherit" récupère la valeur du parent pour une propriété donnée .enfant { display: grid; margin: 2rem; color: hotpink; } 1 2 3 4 5
  31. INITIAL valeur par défaut dans les specs .parent { display:

    grid; margin: 2rem; color: hotpink; } 1 2 3 4 5 .enfant { all: initial; } 1 2 3 “"initial" applique la valeur par défaut pour une propriété donnée (= celle prévue par les Spécifications CSS) .enfant { display: inline; margin: 0; color: canvastext; } 1 2 3 4 5
  32. INITIAL valeur par défaut dans les specs .parent { display:

    grid; margin: 2rem; color: hotpink; } 1 2 3 4 5 .enfant { all: initial; } 1 2 3 Toutes les propriétés ont une valeur initiale (exemple display vaut inline). Elle est parfois écrasée par le navigateur (exemple div {display: block}) max-width: initial; = none width: initial; = auto position: initial; = static color: initial; = canvastext
  33. UNSET initial ou inherit .parent { display: grid; margin: 2rem;

    color: hotpink; } 1 2 3 4 5 .enfant { all: unset; } 1 2 3 “"unset" applique la valeur du parent si la propriété peut être héritée ou la valeur initiale dans le cas contraire. .enfant { display: inline; margin: 0; color: hotpink; } 1 2 3 4 5
  34. .parent { display: grid; margin: 2rem; color: hotpink; } 1

    2 3 4 5 .enfant { all: unset; } 1 2 3 font-size: unset; = inherit (propriété héritable) color: unset; = inherit (propriété héritable) width: unset; = initial = auto max-width: unset; = initial = none position: unset; = initial = static UNSET initial ou inherit
  35. ALL: UNSET; 💖 👎 👍

  36. REVERT valeur donnée par le navigateur .parent { display: grid;

    margin: 2rem; color: hotpink; } 1 2 3 4 5 div.enfant { all: revert; } 1 2 3 “ "revert" récupère la valeur donnée par le navigateur. S'il n'y en a pas, "revert" devient "unset" 🤯 div.enfant { display: block; margin: 0; color: hotpink; } 1 2 3 4 5
  37. .parent { display: grid; margin: 2rem; color: hotpink; } 1

    2 3 4 5 div.enfant { all: revert; } 1 2 3 div {display: revert} = block span {display: revert} = inline input {display: revert} = inline-block REVERT valeur donnée par le navigateur
  38. None
  39. 3 mais carrément utilisables en prod LES "PAS TRÈS CONNUES"

  40. LES "PAS TRÈS CONNUES" 3 backdrop-filter propriétés logiques media queries

    d'interaction prefers-color-scheme media query prefers-reduced-motion media query scroll-behavior scroll-snap mais carrément utilisables en prod
  41. BACKDROP-FILTER un filtre *derrière* un élément body:has(.modal) { backdrop-filter: blur(8px);

    } 1 2 3 https://codepen.io/raphaelgoetter/pen/VwdZmGx?editors=1100
  42. BACKDROP-FILTER un filtre *derrière* un élément .element { backdrop-filter: blur(2px);

    backdrop-filter: brightness(60%); backdrop-filter: contrast(40%); backdrop-filter: drop-shadow(4px 4px 10px blue); backdrop-filter: grayscale(30%); backdrop-filter: hue-rotate(120deg); backdrop-filter: invert(70%); backdrop-filter: opacity(20%); backdrop-filter: sepia(90%); backdrop-filter: saturate(80%); /* Multiple filters */ backdrop-filter: url(filters.svg#filter) blur(4px); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter
  43. PROPRIÉTÉS LOGIQUES sensibles au sens de lecture https://css-tricks.com/css-logical-properties-and-values/

  44. PROPRIÉTÉS LOGIQUES en action p { text-align: left; } 1

    2 3 p { text-align: start; } 1 2 3 valeur physique valeur logique .box { padding-left: 20px; padding-right: 20px; } 1 2 3 4 .box { padding-inline: 20px; } 1 2 3 .card { margin-bottom: 20px; } 1 2 3 .card { margin-block-end: 20px; } 1 2 3 body { width: 1000px; min-height: 100vh; } 1 2 3 4 body { inline-size: 1000px; min-block-size: 100vh; } 1 2 3 4
  45. PROPRIÉTÉS LOGIQUES résumé https://css-tricks.com/css-logical-properties-and-values/

  46. https://codepen.io/raphaelgoetter/pen/zWdOrJ MEDIA QUERIES D'INTERACTION pour détecter le type d'input du

    device @media (pointer: coarse) { body::after { content :" 📱🎮 "; } } @media (pointer: fine) { body::after { content :" 🖥💻 "; } } 1 2 3 4 5 6 7 8 9 10
  47. https://css-tricks.com/interaction-media-features-and-their-potential-for-incorrect-assumptions/ MEDIA QUERIES D'INTERACTION pour détecter le type d'input du

    device @media (pointer: fine) { /* using a mouse or stylus - ok to use small buttons/controls */ } @media (pointer: coarse) { /* using touch - make buttons and other "touch targets" bigger */ } @media (hover: hover) { /* ok to use :hover-based menus */ } @media (hover: none) { /* don't use :hover-based menus */ } 1 2 3 4 5 6 7 8 9 10 11 12
  48. https://web.dev/prefers-color-scheme/ PREFERS-COLOR-SCHEME bienvenue au Dark Mode :root { --color-one: chocolate;

    --color-two: honeydew; } @media (prefers-color-scheme: dark) { /* redefine dark mode colors here */ :root { --color-one: honeydew; --color-two: chocolate; } } .card { background-color: var(--color-one); color: var(--color-two); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  49. PREFERS-REDUCED-MOTION prise en compte des préférences d'animation /* Applies styles

    when Reduced Motion is enabled */ @media (prefers-reduced-motion: reduce) { } /* Applies styles when the user has made no preference known */ @media (prefers-reduced-motion: no-preference) { } 1 2 3 4 5
  50. PREFERS-REDUCED-MOTION fichier "reset" pour les animations https://web.dev/prefers-reduced-motion/ @media (prefers-reduced-motion: reduce)

    { *, *::before, *::after { animation: none !important; transition: none !important; background-attachment: initial !important; scroll-behavior: auto !important; } } 1 2 3 4 5 6 7 8 9 10
  51. SCROLL-BEHAVIOR un peu de douceur lors du scroll html {

    scroll-behavior: smooth; } 1 2 3 https://codepen.io/alsacreations/pen/GaebzJ?editors=1100
  52. SCROLL-SNAP des points d'accroche lors du scroll .slides { overflow-x:

    auto; scroll-snap-type: x mandatory; /* point d'accroche sur l'axe x */ } .slide { scroll-snap-align: center; } 1 2 3 4 5 6 7 https://codepen.io/raphaelgoetter/pen/MWJqmRX
  53. LES "GAME CHANGERS" 4 qui changent vraiment la donne

  54. LES "GAME CHANGERS" 4 Cascade Layers content-visibility display: contents :has()

    qui changent vraiment la donne
  55. CSS LAYERS au service de la maintenabilité p {color: tomato;}

    .kiwi {color: pink;} div p:first-child {color: chocolate;} p.kiwi {color: hotpink;} 1 2 3 4 de quelle couleur est <p> ? 😢 <p class="kiwi">Coucou !</p> 1 “@layer permet de redéfinir l'ordre et la priorité dans la cascade CSS @layer reset { p {color: olive;} .kiwi {color: pink;} div p:first-child {color: chocolate;} } @layer base { p {color: hotpink;} } 1 2 3 4 5 6 7 8 <p> sera de couleur hotpink <p> sera de couleur chocolate
  56. il est possible de définir l'ordre de plusieurs layers en

    une règle @layer reset, base; @layer base { p {color: tomato;} } @layer reset { p {color: olive;} .kiwi {color: pink;} } 1 2 3 4 5 6 7 8 9 10 <p> sera de couleur tomato les styles sans layers sont appliqués en priorité p {color: tomato;} @layer reset { p {color: olive;} .kiwi {color: pink;} } 1 2 3 4 5 6 <p> sera de couleur tomato on peut importer des styles dans des layers @layer framework, base; @import url("bootstrap.css") layer("framework"); @layer base { p {color: tomato;} } 1 2 3 4 5 6 7 <p> sera de couleur tomato
  57. CONTENT-VISIBILITY “content-visibility indique au navigateur que si l'élément est en

    dehors du Viewport, il n'a pas besoin d'être traité (ni rendering, ni layout, ni painting). au service de la performance <section>... <section>... <section>... <section>... ... 1 2 3 4 5 ah ben on dirait que le document est vraiment très long, avec beaucoup de sections (par exemple) "hack" pour que les boîtes n'aient pas une hauteur nulle par défaut quand hors viewport section { content-visibility: auto; contain-intrinsic-size: 1px 5000px; } 1 2 3 4
  58. https://caniuse.com/css-content-visibility https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility CONTENT-VISIBILITY compatibilité

  59. DISPLAY: CONTENTS l'élément ne génère plus de boîte header {

    display: flex; } input { flex-grow: 1; } 1 2 3 4 5 6 Aucune chance que ça fonctionne puisque input n'est pas enfant direct de header logo label input <header> <img class="logo"> <form> <label></label> <input> </form> </header> 1 2 3 4 5 6 7
  60. DISPLAY: CONTENTS l'élément ne génère plus de boîte header {

    display: flex; } form { display: contents; } input { flex-grow: 1; } 1 2 3 4 5 6 7 8 9 form ne crée plus de boîte, ses enfants deviennent les enfants directs de header logo label input <header> <img class="logo"> <form> <label></label> <input> </form> </header> 1 2 3 4 5 6 7
  61. DISPLAY: CONTENTS compatibilité Tu veux tester ? Tu veux en

    savoir plus ? Le ? Les ? https://codepen.io/raphaelgoetter/pen/BaJyQmN display-box (dont la valeur contents) support navigateurs bugs restants en accessibilité
  62. :HAS() le sélecteur "de parent" a:has(img) { color: hotpink; }

    1 2 3 cible les liens qui contiennent une image a:has(> img) { color: hotpink; } 1 2 3 cible le lien parent direct d'une image label:has(+ input) { color: hotpink; } 1 2 3 cible le label précédent un input
  63. :HAS() je veux cibler body quand il y a une

    modale body:has(.modal) { backdrop-filter: blur(8px); } 1 2 3 https://codepen.io/raphaelgoetter/pen/VwdZmGx?editors=1100
  64. :HAS() je veux cibler .card uniquement quand il y a

    une image https://codepen.io/raphaelgoetter/pen/vYdVQPX Je veux une gouttière ici, mais uniquement quand il y a une image .card { display: grid; } .card:has(>img) { column-gap: 20px; } 1 2 3 4 5 6
  65. :HAS() je veux une couleur de fond quand un enfant

    est coché .form-check:has(:checked) { background: #ddd; } .form-check:has(:checked) > label { font-weight: 700; } 1 2 3 4 5 6 https://codepen.io/raphaelgoetter/pen/MWXwpaJ?editors=1100
  66. :HAS() compatibilité https://caniuse.com/css-has

  67. LES "ALLEZ, ON Y EST PRESQUE" bonus

  68. LES "ALLEZ, ON Y EST PRESQUE" bonus Media Queries Ranges

    Viewport Dynamique Container Queries
  69. https://developer.chrome.com/blog/media-query-range-syntax/ MEDIA QUERIES RANGES enfin une syntaxe compréhensible ! /*

    🎉 */ @media (480px <= width <= 1024px) { .grid { grid-template-columns: 1fr 1fr; } } 1 2 3 4 5 6 /* */ @media (min-width: 480px) and (max-width: 1024px) { .grid { grid-template-columns: 1fr 1fr; } } 1 2 3 4 5 6
  70. https://caniuse.com/css-media-range-syntax MEDIA QUERIES RANGES compatibilité

  71. (source image : ) https://www.bram.us/2021/07/08/the-large-small-and-dynamic-viewports/ LE VIEWPORT DYNAMIQUE les unités

    dvh / dvw / dvmin / dvmax
  72. “Le Viewport Dynamique s'adapte à l'interface de l'Agent Utilisateur. Sa

    valeur est contenue entre 100vh (maximum) and 100svh (minimum). “Viewport”: vh / vw / vmin / vmax “Large Viewport”: lvh / lvw / lvmin / lvmax “Small Viewport”: svh / svw / svmin / svmax “Dynamic Viewport”: dvh / dvw / dvmin / dvmax LE VIEWPORT DYNAMIQUE les unités dvh / dvw / dvmin / dvmax body { min-height: 100dvh; /* 👍 */ } 1 2 3
  73. https://caniuse.com/viewport-unit-variants LE VIEWPORT DYNAMIQUE compatibilité

  74. (source image : ) "Say Hello To CSS Container Queries"

    CONTAINER QUERIES au service du Responsive
  75. CONTAINER QUERIES au service du Responsive <aside class="sidebar"> <article class="article"></article>

    </aside> 1 2 3 Contexte de Confinement créé sur .sidebar. "kiwi" est son nom "inline-size" est le critère à tester (ici c'est la largeur de .sidebar) .sidebar { container-name: kiwi; container-type: inline-size; } 1 2 3 4 Container Query si le conteneur "kiwi" a une largeur mini de 25rem alors on applique des styles conditionnels sur .article @container kiwi (min-width: 25rem) { .article { /* styles à appliquer */ } } 1 2 3 4 5
  76. https://caniuse.com/css-container-queries https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries https://github.com/GoogleChromeLabs/container-query-polyfill CONTAINER QUERIES compatibilité

  77. WOW c'était intense ! Raphaël Goetter alsacréations @goetter https://speakerdeck.com/goetter