Expérience
Une carte marquée .card--special conserve toute la largeur de la grille.
Création de sites web au fil du temps depuis 1996 *
Un inventaire vivant des variables de design, de l'échelle typographique, des primitives de mise en page et des composants de cybmed.com.
Chaque exemple de cette page est rendu par la feuille de styles du site plutôt que recopié dedans. Modifiez quelque chose dans assets/scss/styles.scss ou assets/scss/_variables.scss et le changement apparaît ici aussi. Utilisez le bouton soleil/lune de la navigation pour vérifier chaque motif dans les deux thèmes.
Toutes les variables sont des propriétés personnalisées CSS déclarées sur :root dans _variables.scss. La palette brute ci-dessous ne change jamais d'un thème à l'autre ; ce sont les variables sémantiques plus bas qui sont réellement remappées en mode sombre.
Valeurs fixes. Préférez toujours une variable sémantique à l'une d'elles pour styler un nouvel élément — c'est ce qui fait fonctionner le mode sombre sans effort.
--brand-color#d80000 (via --logo-color)--theme-color#663399 · rebeccapurple--schoolbusyellow#f1d302--fireenginered#c1292e--firebrickfirebrick--huntergreen#3f6c51--cerulean#0c7489--babypowder#fdfffc--lightgray#e7e7e7--midgray#7a7a7a--darkgray#3c3c3cTrois formes complémentaires existent pour l'interpolation : --brand-color-hsl, --theme-color-hsl et --theme-color-rgb (séparée par des espaces, 102 51 153, afin de pouvoir écrire rgb(var(--theme-color-rgb) / 0.25)). Les variables dérivées --theme-10 et --theme-25 encapsulent exactement cela.
Uniquement référencées depuis le mixin dark-theme-cvars — à ne jamais utiliser directement dans un composant.
--dark-banner-color#582f81--dark-page-bg-color#391b57--dark-footer-color#211231--dark-text-colorrgba(255, 255, 255, 0.75)--dark-link-colorwhite--dark-link-visited-colorrgba(255, 255, 255, 0.25)Ce sont celles à utiliser. La pastille de chaque ligne se résout en direct : elle suit donc le thème que vous consultez actuellement.
| Variable | Clair | Sombre | Utilisée pour |
|---|---|---|---|
--page-bg-color | #fff | var(--dark-page-bg-color) | Fond de main, et de nav/footer au-delà du point de rupture l |
--text-color | #3a3a3a | var(--dark-text-color) | Texte courant sur body |
--banner-color | var(--theme-color) | var(--dark-banner-color) | La bande header, ainsi que les vagues qui la prolongent |
--banner-text | white | white | Texte posé sur la bannière |
--footer-color | var(--theme-color) | var(--dark-footer-color) | Bande de pied de page sur les écrans étroits |
--footer-text-wide | var(--banner-color) | var(--dark-text-color) | Texte du pied de page une fois celui-ci sur le fond de page |
--link-color | var(--brand-color) | var(--dark-link-color) | Couleur de lien au repos |
--link-hover-color | var(--theme-color) | var(--brand-color) | Survol — notez que les deux thèmes inversent la paire |
--link-visited-color | var(--firebrick) | var(--dark-link-visited-color) | Liens visités |
--link-active-color | var(--theme-color) | var(--dark-link-active-color) | Liens actifs/pressés |
--text-deco-color | var(--theme-color) | var(--dark-text-color) | Icônes placées dans un h2 |
--hilite-bg-color | aliceblue | var(--dark-banner-color) | Fond de la bande .is-hilited |
--client-bg-strong | var(--theme-25) | var(--dark-banner-color) | Étiquettes des clients mis en avant |
--client-text-color | var(--theme-color) | var(--dark-text-color) | Libellé des étiquettes clients |
--client-outline-color | var(--theme-color) | var(--dark-text-color) | Contour tireté des étiquettes clients |
--header-bg-color | white | — non remappée | Fond de html, derrière tout le reste |
--theme-toggle-color | var(--schoolbusyellow-hsl) | — non remappée | Icône soleil/lune ; passe au rouge de marque au-delà de l |
Le mode sombre s'applique de deux manières, toutes deux alimentées par le même mixin dark-theme-cvars : [data-theme="dark"] lorsque la personne a fait un choix, et @media (prefers-color-scheme: dark) .no-js en repli lorsque le script de bascule n'a pas pu s'exécuter. Les images passent également à opacity: .75 en mode sombre et retrouvent leur opacité complète au survol.
| Variable | Clair | Sombre | Utilisée pour |
|---|---|---|---|
--space | 1.5rem | — | Pas du rythme vertical, consommé par .flow |
--gutter | 2rem | — | Gouttière générique ; pilote aussi --icon-deco-scale |
--max-text-width | 70ch | — | Limite de longueur de ligne sur p, h2, h3 |
--max-content-width | 48rem | — | 768px — limite de contenu étroit |
--max-content-lg-width | 90rem | — | 1440px — limite de main, nav, footer |
--max-content-xxl-width | 105rem | — | 1680px |
--wrapper-inline-padding | 2rem | — | Référence de marge intérieure horizontale des conteneurs |
La limite de longueur de ligne se perd facilement de vue ; la voici donc dessinée :
Ce paragraphe s'étend exactement jusqu'à --max-text-width. Au-delà, la ligne devient fatigante à lire ; la règle s'applique automatiquement à p, h2 et h3, ce qui explique pourquoi le texte courant n'a jamais besoin de sa propre largeur.
Chaque variable fluide est un clamp() généré avec Utopia. Les barres ci-dessous sont dimensionnées par la variable elle-même — redimensionnez la fenêtre et elles bougent.
--fluid-4-16 4 → 16px · rayon du logo--fluid-16-32 16 → 32px--fluid-16-36 16 → 36px · mission--fluid-16-48 16 → 48px--fluid-24-48 24 → 48px--fluid-24-64 24 → 64px--fluid-32-48 32 → 48px--fluid-32-64 32 → 64px--fluid-36-72 36 → 72px · titre de marque--fluid-48-128 48 → 128px · largeur du logoIl existe aussi des clamp() propres à certains composants, nommés d'après ce qu'ils pilotent plutôt que d'après leur intervalle : --header-fluid-32-48, --branding-fluid-16-32, --branding-title-fluid-48-56, --branding-title-fluid-l-48-72, --mission-fluid-20-30, --logo-fluid-8-12, --logo-fluid-8-16, --logo-fluid-56-72, --logo-fluid-64-96.
Une seule police pour l'ensemble du site : Raleway, auto-hébergée en woff2 et déclarée à la fois pour --header-font-family et --body-font-family, avec sans-serif en repli. Les règles @font-face sont générées et intégrées par snippets/head-fonts-local.inc.php ; les graisses 300, 400 et 900 sont préchargées.
Sept variables de graisse sont déclarées, mais seules cinq coupes droites et trois italiques sont réellement téléchargées. Utiliser une graisse non chargée donne une approximation synthétisée par le navigateur, pas du vrai Raleway.
| Variable | Valeur | Chargée | Exemple |
|---|---|---|---|
--font-weight-thin | 100 | Non — synthétisée | Building websites |
--font-weight-lighter | 200 | Non — synthétisée | Building websites |
--font-weight-light | 300 | Oui, + italique, préchargée | Building websites |
--font-weight-normal | 400 | Oui, + italique, préchargée | Building websites |
--font-weight-semibold | 600 | Oui, + italique | Building websites |
--font-weight-bold | 800 | Oui | Building websites |
--font-weight-black | 900 | Oui, préchargée | Building websites |
À noter : --font-weight-bold correspond à 800 (ExtraBold) et non au 700 habituel — le 700 n'est jamais chargé. --font-weight-heading en est un alias, tous les titres sont donc rendus en 800.
Le texte courant est défini une seule fois sur body ; tout le reste lui est relatif.
--line-height-base à 1.56.--font-weight-lede (300)..contentinfo du pied de page.Les titres partagent --line-height-base: 1.2 (resserré via une surcharge :where()) et la graisse 800. Seuls h2 et h3 ont une taille explicite ; h1, h4 et h5 retombent sur la valeur par défaut du navigateur, relative à la base de 18px.
<h1>Handmade web design</h1>
<h2>Withstanding the test of time</h2>
<h3>Fiercely independent</h3>
<h4>A smaller subdivision</h4>
<h5>Rarely needed</h5>
Le spécimen ci-dessus rend volontairement un vrai h1 afin de pouvoir comparer l'échelle, ce qui fait de cette page le seul endroit du site qui en porte deux — acceptable ici puisqu'il s'agit d'un outil interne en noindex. Partout ailleurs : un seul h1 par page, et sur la page d'accueil ce h1 est le titre de marque dans la bannière, le corps de la page démarrant donc au h2 — voir content/all-header.fr.inc.php.
Un h2 contenant un svg.deco devient une rangée flex et adopte --text-deco-color. Aucune classe supplémentaire n'est nécessaire — la règle est :where(h2):has(> .deco).
<h2><svg class="deco" height="1em" width="1.1em" viewBox="0 0 512 512" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#heart"/></svg> Passion</h2>
Cybermedia Concepts est un studio de web design d'une seule personne basé à Genève, en Suisse, axé sur la performance, l'accessibilité et les standards.
La simplicité et la clarté sont devenues notre obsession. Nos designs sont soigneusement façonnés pour répondre à vos besoins. Le texte courant est limité à --max-text-width afin que la longueur de ligne reste confortable, quelle que soit la largeur de la fenêtre.
— « La confiance est la monnaie des relations durables. Bâtie lentement, dépensée avec soin, elle transforme un premier client en allié de toujours. »
<div class="flow">
<p class="lede">Cybermedia Concepts est un <a href="/fr/about/">studio de web design d'une seule personne</a> basé à Genève, en Suisse, axé sur la performance, l'accessibilité et les standards.</p>
<p>La simplicité et la clarté sont devenues notre obsession. Nos designs sont soigneusement façonnés pour répondre à vos besoins. Le texte courant est limité à <code>--max-text-width</code> afin que la longueur de ligne reste confortable, quelle que soit la largeur de la fenêtre.</p>
<blockquote><em>— « La confiance est la monnaie des relations durables. Bâtie lentement, dépensée avec soin, elle transforme un premier client en allié de toujours. »</em></blockquote>
</div>
.lede est normalement en light (300) ; à l'intérieur de .page--home il passe en semibold, et le strong qu'il contient passe à 600 plutôt qu'à 800. blockquote n'a aucun style propre au-delà du reset — l'italique vient du balisage.
La couleur de lien s'applique à tous les a sauf .plain et .branding--link. Les états de survol et actif permutent entre le rouge de marque et le rebeccapurple selon le thème, ce qui garde les deux sens distinguables.
--link-color--link-hover-color--link-visited-color.underline, décalage de 3px.plain, hérite la couleur, sans décorationabbr affiche un curseur d'aide<ul role="list" class="flow" style="--space: .5rem">
<li><a href="#typography">Un lien standard</a> — <code>--link-color</code></li>
<li><a href="#typography" style="color: var(--link-hover-color)">État de survol</a> — <code>--link-hover-color</code></li>
<li><a href="#typography" style="color: var(--link-visited-color)">État visité</a> — <code>--link-visited-color</code></li>
<li><a href="#typography" class="underline">Souligné explicitement</a> — <code>.underline</code>, décalage de 3px</li>
<li><a href="#typography" class="plain">Lien sans habillage</a> — <code>.plain</code>, hérite la couleur, sans décoration</li>
<li><abbr title="Une infobulle apparaît au survol">Une abréviation</abbr> — <code>abbr</code> affiche un curseur d'aide</li>
</ul>
Les deuxième et troisième éléments ci-dessus sont peints avec la variable d'état afin de pouvoir comparer les quatre côte à côte ; dans du vrai balisage, on ne les définit jamais à la main. À l'intérieur de nav et footer, sous le point de rupture l, les variables de lien sont surchargées localement en blanc sur violet.
Neuf paliers nommés vivent dans la map Sass $breakpoints et sont interrogés via le mixin mq() : @include m.mq(l) pour un min-width, @include m.mq(l, max) pour un max-width (qui retranche 0.02px afin d'éviter le trou des fenêtres à largeur fractionnaire). Ils sont également exportés en propriétés personnalisées --bp-*.
| Nom | Valeur | px | Ce qui change |
|---|---|---|---|
xs | 20rem | 320 | La marque s'aligne horizontalement |
xss | 32rem | 512 | — |
s | 48rem | 768 | .wrapper gagne 2rem de marge ; les cartes passent à deux par rangée |
sl | 50rem | 800 | Palier de requête de conteneur pour .grid-flow--2 |
m | 62rem | 992 | L'en-tête devient une rangée ; la mission s'aligne à gauche |
l | 80rem | 1280 | Le grand saut — la page devient une grille à trois colonnes |
xl | 90rem | 1440 | .is-wide cesse de déborder |
xxl | 100rem | 1600 | Retour d'une marge 5vw symétrique ; cartes à trois par rangée |
xxxl | 128rem | 2048 | .is-hilited gagne des coins arrondis en fin de ligne |
Sous l, la page est un simple empilement vertical : bannière, navigation, contenu, pied de page. À partir de l, body devient une grille CSS — une colonne de bannière fixe de 25vw à gauche, une colonne de 5rem qui accueille la vague verticale, puis la colonne de contenu à droite.
Comme header couvre les trois rangées de contenu, la couleur de bannière court sur toute la hauteur de la page sur grand écran, et nav comme footer basculent sur le fond de page (--footer-text est localement réassignée à --footer-text-wide pour que leur texte reste lisible).
Le conteneur horizontal de tout ce qui se trouve dans main et footer. Sous s, il n'a pas de marge horizontale et se limite à la longueur de ligne ; à partir de s il prend 2rem de marge et libère cette limite ; à partir de l, la marge passe à 4rem.
Le contenu standard prend place dans un wrapper. Presque tous les blocs du site s'ouvrent avec exactement cette paire de classes.
<div class="wrapper flow">
<h3>Un titre de section</h3>
<p>Le contenu standard prend place dans un wrapper. Presque tous les blocs du site s'ouvrent avec exactement cette paire de classes.</p>
</div>
Le sélecteur « chouette » qui gère tout le rythme vertical : .flow > * + * reçoit margin-block-start: var(--space). Les titres portent --space à 2rem avant eux et le redescendent à 0.5em après, afin qu'un titre reste collé au texte qu'il introduit. Surchargez-le bloc par bloc avec style="--space: .5rem", comme le font la grille du blog et le corps des cartes.
Flux resserré — --space abaissé à .5rem.
L'écart au-dessus de ce paragraphe est celui qui a été surchargé.
…et ceci se place à 0.5em en dessous, parce que la règle des titres l'emporte.
<div class="flow" style="--space: .5rem">
<p>Flux resserré — <code>--space</code> abaissé à .5rem.</p>
<p>L'écart au-dessus de ce paragraphe est celui qui a été surchargé.</p>
<h4>Un titre conserve malgré tout ses 2rem</h4>
<p>…et ceci se place à 0.5em en dessous, parce que la règle des titres l'emporte.</p>
</div>
Une bande teintée pleine largeur. Elle annule la marge horizontale du wrapper par des marges négatives, puis la rajoute, de sorte que le fond atteigne le bord de la fenêtre pendant que le texte reste aligné avec le reste. La dernière bande d'une page reçoit une marge basse supplémentaire pour rejoindre proprement la vague du pied de page.
Utilise --hilite-bg-color : aliceblue en mode clair, le violet sombre de la bannière en mode sombre.
<div class="wrapper is-hilited flow">
<h3>Sur le blog</h3>
<p>Utilise <code>--hilite-bg-color</code> : aliceblue en mode clair, le violet sombre de la bannière en mode sombre.</p>
</div>
Présentée ici dans un encadré de démonstration, le débordement est donc rogné. Sur une vraie page, elle court d'un bord à l'autre. La variante .section--blog remplace la teinte par #e3d8f1 et supprime le soulignement des liens.
Trois façons de découper une page, par ordre décroissant de force.
<hr class="section-rule">
<hr class="row-rule">
.section-rule est un filet double de 3px avec un pied-de-mouche centré détouré dedans. .row-rule est pointillé et masqué par défaut — il n'apparaît qu'à l'intérieur d'un conteneur .grid assez large pour déclencher la requête de conteneur main-grid. Les deux disparaissent automatiquement lorsqu'ils jouxtent un .is-hilited.
La bannière et le pied de page sont raccordés à la page par des vagues SVG : .h-wave horizontalement sous l, .v-wave verticalement au-delà, la copie du pied de page étant pivotée à 180°. Les deux prennent --banner-color et suivent donc le thème. Entre les sections, snippets/icon-deco.inc.php dépose une rangée mélangée d'icônes du sprite à 50 % d'opacité, avec une icône « héroïne » tirée au sort en rouge de marque — c'est la rangée juste sous le sommaire de cette page.
.grid est une boîte flex avec retour à la ligne, qui se déclare aussi conteneur nommé (main-grid). Ajoutez .gx2 pour limiter les cartes à la demi-largeur dès s, et .gx3 pour les limiter au tiers dès xxl. .card--special exclut une carte de la limite à deux colonnes, ce qui lui permet d'occuper toute la largeur.
Une carte marquée .card--special conserve toute la largeur de la grille.
Une carte simple, limitée à la moitié de la grille dès le point de rupture s.
Les cartes n'ont ni fond ni bordure propres — seulement l'icône de titre et la limite de longueur de ligne.
<div class="articles grid gx2 gx3">
<article class="card card--special">
<h2><svg class="deco" height="1em" width="1.1em" viewBox="0 0 512 512" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#certificate"/></svg> Expérience</h2>
<p>Une carte marquée <code>.card--special</code> conserve toute la largeur de la grille.</p>
</article>
<article class="card">
<h2><svg class="deco" height="1em" width="1.1em" viewBox="0 0 512 512" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#handshake"/></svg> Confiance</h2>
<p>Une carte simple, limitée à la moitié de la grille dès le point de rupture <code>s</code>.</p>
</article>
<article class="card">
<h2><svg class="deco" height="1em" width="1.1em" viewBox="0 0 512 512" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#leaf"/></svg> Écologie</h2>
<p>Les cartes n'ont ni fond ni bordure propres — seulement l'icône de titre et la limite de longueur de ligne.</p>
</article>
</div>
La seule variante de carte dotée d'une surface : un remplissage violet translucide et un contour translucide plus marqué. En mode clair, son texte et ses liens sont forcés à --theme-color.
Construite à partir de rgb(var(--theme-color-rgb) / 0.25) avec un contour de 3px à 0.5 d'alpha et un rayon de 0.5rem.
<div class="card-outline flow" style="--space: .5rem">
<h4>On commence ?</h4>
<p>Construite à partir de <code>rgb(var(--theme-color-rgb) / 0.25)</code> avec un contour de 3px à 0.5 d'alpha et un rayon de 0.5rem.</p>
<p><a href="/fr/tc/">Lire les conditions de collaboration</a></p>
</div>
Une grille à remplissage automatique avec une piste minimale de 224px. Les cartes sont alimentées à la requête par promotedPosts(), qui récupère un flux JSON depuis davidroessli.com et le met en cache 30 minutes. Toute la carte est cliquable : .card__body--link étire un pseudo-élément sur son parent .card positionné.
<div class="articles blog" style="--space: 2em; --font-weight-heading: var(--font-weight-semibold)">
<article class="card flow" style="--space: .5rem">
<div class="card__media">
<figure></figure>
</div>
<div class="card__body flow">
<h3 class="card__body--h3"><a class="card__body--link" href="#components">Un titre d'article d'exemple qui court sur deux lignes</a></h3>
</div>
<div class="card__footer card__footer--hashtags">#css #accessibilite</div>
</article>
<article class="card flow" style="--space: .5rem">
<div class="card__media">
<figure></figure>
</div>
<div class="card__body flow">
<h3 class="card__body--h3"><a class="card__body--link" href="#components">Un titre plus court</a></h3>
</div>
<div class="card__footer card__footer--hashtags">#webdev</div>
</article>
</div>
Les éléments figure sont laissés vides ici afin de montrer le remplissage de remplacement :empty — en production, ils contiennent une vignette webp chargée paresseusement et dérivée du slug de l'article, avec des coins supérieurs arrondis.
.list-multicol est la liste d'étiquettes générique ; .list-clients en est l'habillage de la page « travaux », qui y injecte les variables --client-*. .is-featured remplit l'étiquette et supprime le contour ; .is-current signale une relation en cours.
<ul class="list-multicol list-clients" style="--justify-content: start" role="list">
<li class="list-item">Un ancien client</li>
<li class="list-item is-featured">Un client mis en avant</li>
<li class="list-item is-current"><a class="plain" href="#components">Un client actuel</a></li>
<li class="list-item is-featured is-current">Mis en avant et actuel</li>
<li class="list-item">Encore un autre</li>
</ul>
L'alignement se pilote avec les propriétés personnalisées --justify-content et --text-align plutôt qu'avec des classes modificatrices ; la page « travaux » les passe en style en ligne.
<ul role="list" class="list-inline">
<li class="list-item list-item--inline"><a href="#components">à propos</a></li>
<li class="list-item list-item--inline"><a class="active" aria-current="page" href="#components">travaux</a></li>
<li class="list-item list-item--inline">un troisième élément</li>
</ul>
C'est le motif de .main-nav. À l'intérieur de nav, il reçoit en plus la mise en capitales, la taille xs, et un soulignement sur l'élément dont le lien porte .active (.list-item--inline:has(.active)). Ajoutez --around pour un space-around au lieu de space-between — c'est ce qu'utilise la rangée des réseaux sociaux du pied de page.
Un SVG soleil/lune animé. Le soleil grandit et ses rayons s'effacent tandis qu'un cercle de masque glisse pour découper le croissant, le tout sur les courbes d'accélération Open Props et entièrement neutralisé sous prefers-reduced-motion. Les couleurs d'icône viennent de --icon-fill / --icon-fill-hover, qui passent du jaune scolaire sur la bannière violette au rouge de marque dès que la navigation repose sur le fond de page, à l.
<button class="theme-toggle" title="Basculer entre le mode clair et sombre" aria-label="light" aria-live="polite">
<svg class="sun-and-moon" aria-hidden="true" width="24" height="24" viewBox="0 0 24 24"><mask class="moon" id="sg-moon-mask"><rect x="0" y="0" width="100%" height="100%" fill="white"></rect><circle cx="24" cy="10" r="6" fill="black"></circle></mask><circle class="sun" cx="12" cy="12" r="6" mask="url(#sg-moon-mask)" fill="currentColor"></circle><g class="sun-beams" stroke="currentColor"><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></g></svg>
</button>
Cette copie est inerte — l'identifiant du masque est renommé et le crochet id="theme-toggle" est omis, afin qu'elle n'entre pas en conflit avec le vrai contrôle de la navigation. Le contrôle fonctionnel se trouve dans content/all-theme-toggle.inc.php ; le script qui le pilote est intégré dans le head pour que le thème soit fixé avant le premier rendu.
Chaque page définit hreflang-en et hreflang-fr, et la bascule pointe simplement vers la page équivalente. Elle apparaît deux fois : en version compacte dans la navigation (une icône de globe et un code à deux lettres) et sous forme de phrase complète dans le pied de page, toujours formulée dans la langue vers laquelle elle mène.
<div class="langswitch"><a class="langswitch--link" href="#components" title="Switch to the English version of this page"><svg class="deco" width="1em" height="1em" viewBox="0 0 640 640" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#language"/></svg> Do you speak English?</a></div>
Un unique SVG sprite versionné, référencé avec <use href="…#id">. Les icônes héritent de currentColor grâce au reset, et svg { pointer-events: none } laisse les clics traverser jusqu'au lien situé dessous. Utilisez .deco pour la taille de 1em en ligne.
Une icône dimensionnée sur le texte qui l'entoure : en ligne et héritant la couleur.
<p>Une icône dimensionnée sur le texte qui l'entoure : <svg class="deco" viewBox="0 0 512 512" role="img" aria-label=""><use href="/assets/img/icons.1.2.svg#mug-hot"/></svg> en ligne et héritant la couleur.</p>
.contentinfo est une rangée flex avec retour à la ligne, qui passe en nowrap dès s avec des colonnes de flex égal ; en dessous, la dernière colonne est poussée sur toute la largeur de la fenêtre. .contentinfo--smallprint ramène tout son contenu à la taille xs et allège ses titres en semibold.
Cybermedia Concepts
Avenue Industrielle 14
1227 Carouge / Suisse
Téléphone +41 22 343 45 80
Courriel hello@cybmed.com
Les liens sociaux prennent place ici, dans une rangée .list-inline--around.
Tout ce bloc est rendu en --font-size-xs.
<div class="contentinfo">
<div class="contentinfo--locate flow">
<h3>Nous situer</h3>
<p>Cybermedia Concepts<br>Avenue Industrielle 14<br>1227 Carouge / Suisse</p>
</div>
<div class="contentinfo--call flow">
<h3>Nous joindre</h3>
<p>Téléphone <a href="tel:0041223434580">+41 22 343 45 80</a><br>Courriel <a href="mailto:hello@cybmed.com">hello@cybmed.com</a></p>
</div>
<div class="contentinfo--follow flow">
<h3>Nous suivre</h3>
<p>Les liens sociaux prennent place ici, dans une rangée <code>.list-inline--around</code>.</p>
</div>
</div>
<div class="contentinfo--smallprint">
<h3>Les petits caractères</h3>
<p>Tout ce bloc est rendu en <code>--font-size-xs</code>.</p>
</div>
.has-linktip établit le contexte de positionnement et .linktip est la bulle, masquée jusqu'au survol. Le polaroid de la page « à propos » épingle sa propre variante en permanence, en guise de légende.
<p><a class="plain has-linktip" href="#components">Survolez-moi<span class="linktip">…et une bulle apparaît au-dessus</span></a></p>
Le composant polaroid lui-même (.polaroid, .vignette-colorful, .frame) ne fait pas partie de la feuille de styles globale — il vit dans content/about-css.scss et n'est intégré que sur la page « à propos », suivant le même motif par page que ce guide de styles.
Quatre besoins différents, quatre classes différentes — se tromper de classe est la façon habituelle de perdre du contenu accessible.
| Classe | Visuellement | Lecteurs d'écran | À utiliser pour |
|---|---|---|---|
.sr-only | Masqué | Annoncé | Libellés des contrôles réduits à une icône |
.visuallyhidden | Masqué | Annoncé | Idem, version HTML5 Boilerplate ; ajoutez .focusable pour révéler au focus clavier |
.text-assistive | Rogné | Annoncé | Liens d'évitement — à associer à .display-at-top-on-focus |
.hidden | Masqué | Non annoncé | Supprimer réellement du contenu (display: none !important) |
.invisible | Masqué | Non annoncé | Supprimer du contenu tout en conservant sa place |
Il y a un libellé réservé aux lecteurs d'écran juste ici (ce texte est uniquement annoncé, jamais affiché) — inspectez le balisage pour le voir.
<p>Il y a un libellé réservé aux lecteurs d'écran juste ici <span class="sr-only">(ce texte est uniquement annoncé, jamais affiché)</span> — inspectez le balisage pour le voir.</p>
Il y en a trois, injectés par inc/default-page.php avant la navigation, le contenu principal et le pied de page, chacun libellé depuis $site["start-of-*"] et donc traduit. Ils sont rognés jusqu'à recevoir le focus, puis déploient une barre pleine largeur de 80px en haut de la page, avec les couleurs du thème inversées.
<a href="#utilities" class="text-assistive display-at-top-on-focus">Début du contenu principal.</a>
Atteignez le lien ci-dessus avec la touche de tabulation (il est invisible tant qu'il n'a pas le focus) pour voir l'effet. Essayez dans les deux thèmes — l'inversion est intentionnelle.
.float-end fait flotter l'élément vers la fin de ligne, avec 1rem de marge en bas et au début. .float-sm-end fait de même à partir du point de rupture s, mais centre l'élément sur les écrans plus étroits — c'est ce qu'utilise le polaroid de la page « à propos ».
<div class="flow">
<div class="float-end" style="inline-size: 6rem; block-size: 4rem; background-color: var(--theme-25); border-radius: .25rem"></div>
<p><code>.float-end</code> fait flotter l'élément vers la fin de ligne, avec 1rem de marge en bas et au début. <code>.float-sm-end</code> fait de même à partir du point de rupture <code>s</code>, mais centre l'élément sur les écrans plus étroits — c'est ce qu'utilise le polaroid de la page « à propos ».</p>
</div>
| Classe | Effet |
|---|---|
.format--16by9 | 25vh de haut (min. 150px), object-fit: cover, pleine largeur ; 256px dans .article__hero |
.is-wide | Fait déborder un élément au-delà de la marge du wrapper, puis revient à l'alignement dès xl |
.u-shadow | Ombre portée grise et douce sur une img contenue |
.print-only | Masqué à l'écran, inline-block à l'impression |
.clearfix | Contient les flottants à l'ancienne |
Le reset moderne d'Andy Bell avec les ajouts de Stephanie Eckles : quelques comportements sont donc déjà pris en charge et ne devraient pas être réimplémentés composant par composant.
:where(ul, ol)[role="list"] supprime le style de liste — c'est pourquoi chaque liste décorative du site porte role="list".:focus:not(:focus-visible).picture et SVG sont en display: block avec max-width: 100% (les vagues exceptées).text-wrap: pretty et hanging-punctuation.[id] reçoivent 2rem de marge de défilement, et les éléments ayant le focus 8vh en bas.prefers-reduced-motion ramène toutes les transitions et animations à 0.01ms ; les transitions de vue entre documents ne sont activées que si le mouvement est le bienvenu.safe-area) sont respectées sous l : rien ne se cache sous l'encoche ou la barre d'accueil d'un iPhone.Quelques petites choses à savoir avant de partir à la recherche d'un bug qui n'existe pas.
--font-size-lede et --fluid-16-48 sont chacune déclarées deux fois dans _variables.scss ; c'est la seconde déclaration qui l'emporte (respectivement 1.333333333em et le clamp() basé sur vw). Idem pour --icon-deco-scale, qui se résout en --gutter.@media — voir nav et .main-nav dans styles.scss.@container ; ces points de rupture sont donc écrits en rem littéraux..has-border existe mais sa déclaration est commentée : la classe ne fait rien pour l'instant.| Chemin | Contenu |
|---|---|
assets/scss/_variables.scss | Toutes les variables, la map des points de rupture, les mixins du mode sombre |
assets/scss/styles.scss | Mise en page, typographie, composants, utilitaires |
assets/scss/_reset.scss | Reset moderne |
assets/scss/_mixins.scss | mq(), sr-only |
assets/scss/_theme-toggle.scss | Contrôle soleil/lune |
content/{page}-css.scss | CSS propre à une page, intégré dans le head — « à propos » et ce guide de styles |
content/{page}-main.{lang}.inc.php | Balisage de la page |
inc/default-page.php | Le gabarit unique de page |