Structuration de l’interface pour différents périphériques.
8 critères :
Structuration de l’interface pour différents périphériques.
Le flux d’affichage CSS repose sur l’affichage de blocs.
display: inline;
Initialement, les blocs étaient de 2 types :
block
,inline
.Ensuite est arrivé le type inline-block
fusionnant les deux autres types.
block
Les éléments d’affichage block
suivent le comportement des paragraphes.
On parle parfois d’axe vertical.
inline
Les éléments d’affichage inline
suivent le comportement du texte.
On parle parfois d’axe horizontal.
inline-block
Les éléments d’affichage inline-block
suivent le comportement du texte.
Il s’agit toujours de l’axe horizontal.
Tous les éléments sont dans le flux d’affichage, sauf :
Par défaut :
position : static;
Mais ils peuvent aussi recevoir comme valeur :
relative
absolute
fixed
sticky
La position est ensuite modifiée à l’aide des propriétés top
, right
, bottom
et left
.
relative
L’élément est positionné dans le flux normal, puis décalé à l’aide de top
, right
, bottom
et left
.
span {
position: relative;
}
span {
position: relative;
left: 2em;
top: 2em;
}
span {
position: relative;
left: 2em;
top: 2em;
margin: 0 1em;
}
Attention : nouveau contexte d’empilement z-index
.
absolute
L’élément est sorti du flux d’affichage. Il est positionné, à l’aide de top
, right
, bottom
et left
, par rapport au premier ancêtre positionné.
span {
margin: 0 1em;
}
span {
position: absolute;
left: 2em;
top: 2em;
}
div {
}
span {
margin: 0 1em;
}
div {
position: absolute;
width: 75%;
left: 2em;
bottom: 2em;
}
span {
margin: 0 1em;
}
div {
position: absolute;
width: 75%;
left: 2em;
bottom: 2em;
}
span {
position: absolute;
left: 2em;
top: 2em;
margin: 0 1em;
}
Attention : nouveau contexte d’empilement z-index
.
fixed
L’élément est sorti du flux d’affichage. Il est positionné, à l’aide de top
, right
, bottom
et left
, par rapport à la zone d’affichage de la fenêtre.
span {
margin: 1em;
}
span {
position: fixed;
left: 2em;
top: 2em;
margin: 1em;
}
Attention : nouveau contexte d’empilement z-index
.
sticky
L’élément est positionné dans le flux normal. Mais adhérera au bord de la zone d’affichage en fonction de top
, right
, bottom
et left
.
span {
position: sticky;
top: 2em;
}
Attention : nouveau contexte d’empilement z-index
.
Un exemple de positionnement CSS.
p:nth-of-type(3) {
position: relative;
border: 1px solid #88f;
margin: 3em auto;
width: 50%;
}
span {
background-color: #ddd;
color: #000;
border: 1px solid #aaf;
top: 2em;
left: 2em;
margin: 1em;
}
.static {
position: static;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.sticky {
position: sticky;
bottom: 2em;
}
Syntaxe :
float: left | right | none | inline-start | inline-end;
L’élément est retiré du flux normal et doit être placé sur le côté droit ou gauche du conteneur.
Les éléments en ligne (inline
) entourent l’élément.
span {
}
span {
float: left;
}
span {
float: right;
}
span {
float: right;
}
span:nth-child(even) {
float: left;
}
span {
float: right;
width: 2em;
height: 2em;
}
span:nth-child(even) {
float: left;
}
Syntaxe :
clear: left | right | none | inline-start | inline-end;
Spécifie si l’élément doit être décalé en dessous de l’élément flottant précédent.
span {
}
span {
clear: left;
}
span {
clear: right;
}
span {
clear: both;
}
Un exemple d’éléments flottants en CSS.
div {
border: 1px solid #88f;
margin: 1em;
padding: 2em;
float: right;
}
div:nth-child(even) {
float: left;
}
z-index
Syntaxe :
z-index: auto | <integer>;
Définit le « z-order » des éléments positionnés.
.un {
position: absolute;
}
.deux {
position: absolute;
}
.trois {
position: absolute;
}
.un {
position: absolute;
z-index: 5;
}
.deux {
position: absolute;
}
.trois {
position: absolute;
}
.un {
position: absolute;
z-index: 5;
}
.deux {
position: absolute;
z-index: 2;
}
.trois {
position: absolute;
}
z-index
.un {
}
.deux {
}
.trois {
}
.quatre {
}
.cinq {
}
.un {
}
.deux {
z-index: 5;
}
.trois {
z-index: 4;
}
.quatre {
}
.cinq {
z-index: 3;
}
.un {
z-index: 1;
}
.deux {
z-index: 5;
}
.trois {
z-index: 4;
}
.quatre {
z-index: 1;
}
.cinq {
z-index: 3;
}
.un {
z-index: 2;
}
.deux {
z-index: 5;
}
.trois {
z-index: 4;
}
.quatre {
z-index: 1;
}
.cinq {
z-index: 3;
}
.un {
z-index: 2;
}
.deux {
z-index: 5;
}
.trois {
z-index: 4;
}
.quatre {
z-index: 1;
}
.cinq {
z-index: 6;
}
z-index
Un exemple d’utilisation du z-index
.
<div class="un">1
<div class="deux">2</div>
<div class="trois">3</div>
</div>
<div class="quatre">4
<div class="cinq">5</div>
</div>
.un {
z-index: 1;
}
.deux {
z-index: 5;
}
.trois {
z-index: 4;
}
.quatre {
z-index: 1;
}
.cinq {
z-index: 3;
}
Le modèle de boite HTML est constitué :
width
et height
,padding
,border
),margin
.div {
margin: 2em;
}
div {
margin: 1em 2em;
}
div {
margin: 1em 2em 3em 4em;
}
div {
padding: 1em;
}
div {
border-style: solid;
border-width: 1px 2px 3px 4px;
border-color: red, blue;
}
div {
margin-top: 2em;
margin-right: 2em;
margin-bottom: 2em;
margin-left: 2em;
}
div {
margin-top: 1em;
margin-right: 2em;
margin-bottom: 1em;
margin-left: 2em;
}
div {
margin-top: 1em;
margin-right: 2em;
margin-bottom: 3em;
margin-left: 4em;
}
div {
padding-top: 1em;
padding-right: 2em;
padding-bottom: 3em;
padding-left: 4em;
}
div {
border-top: 1px solid red;
margin-right: 2px solid blue;
margin-bottom: 3px solid red;
margin-left: 4px solid blue;
}
Par défaut, width
et height
définissent la zone interne au padding
.
La propriété box-sizing
définit ce comportement.
div {
margin: 20px;
padding: 20px;
border: 5px solid #fff;
width: 100px;
box-sizing: content-box;
}
div {
margin: 20px;
padding: 20px;
border: 5px solid #fff;
width: 100px;
box-sizing: border-box;
}
Le débordement intervient lorsqu’une boite est trop petite pour son contenu, en x, y ou les deux.
Par défaut, le comportement est de déborder de la boite :
La propriété overflow
modifie le comportement du débordement :
div {
overflow: visible;
}
div {
overflow: hidden;
}
div {
overflow: scroll;
}
div {
overflow: auto;
}
Attention, lors de la définition d’une zone « scrollable », une erreur classique consiste à oublier que la taille de la zone doit-être fixée.
Le module « flexbox », est un modèle unidimensionnel permettant d’organiser les éléments d’un conteneur en spécifiant :
Il permet aussi d’agir sur chaque élément pour spécifier comment il doit occuper l’espace.
Le module apparaît en 2009 et après plusieurs itérations, il est stabilisé depuis 2016. Aujourd’hui, il est supporté par la plupart des navigateurs.
Le module s’applique à un conteneur et ses éléments fils sont positionnés.
.conteneur {
display: flex; /* or inline-flex */
}
<div class="conteneur">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
Le module « flexbox » étant unidimensionnel et l’interface bidimensionnel, il faut choisir un axe principal (row
par défaut) :
.conteneur {
display: flex;
flex-direction: row | row-reverse | column | column-reverse;
}
.conteneur {
display: flex;
}
.conteneur {
display: flex;
flex-direction: row;
}
.conteneur {
display: flex;
flex-direction: column;
}
.conteneur {
display: flex;
flex-direction: row-reverse;
}
.conteneur {
display: flex;
flex-direction: column-reverse;
}
La distribution des éléments est réalisée sur l’axe principal (flex-start
par défaut) :
.conteneur {
display: flex;
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
.conteneur {
display: flex;
}
.conteneur {
display: flex;
justify-content: flex-start;
}
.conteneur {
display: flex;
justify-content: flex-end;
}
.conteneur {
display: flex;
justify-content: center;
}
.conteneur {
display: flex;
justify-content: space-between;
}
.conteneur {
display: flex;
justify-content: space-around;
}
.conteneur {
display: flex;
justify-content: space-evenly;
}
L’alignement des éléments est réalisé sur l’axe secondaire (stretch
par défaut) :
.conteneur {
display: flex;
align-items: stretch | flex-start | flex-end | center | baseline;
}
.conteneur {
display: flex;
}
.conteneur {
display: flex;
align-items: stretch;
}
.conteneur {
display: flex;
align-items: flex-start;
}
.conteneur {
display: flex;
align-items: flex-end;
}
.conteneur {
display: flex;
align-items: center;
}
.conteneur {
display: flex;
align-items: baseline;
}
Par défaut, les éléments sont alignés sur une ligne (nowrap
par défaut) :
.conteneur {
display: flex;
flex-wrap: nowrap | wrap | wrap-reverse;
}
.conteneur {
display: flex;
}
.conteneur > * {
width: 3em;
}
.conteneur {
display: flex;
overflow: hidden;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
overflow: hidden;
flex-wrap: nowrap;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
overflow: hidden;
flex-wrap: wrap;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
overflow: hidden;
flex-wrap: wrap-reverse;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
Par défaut, les lignes sont distribuées régulièrement sur l’axe secondaire (normal
par défaut) :
.conteneur {
display: flex;
flex-wrap: wrap;
align-content: normal | stretch | flex-start | flex-end | center | baseline | space-between | space-around | space-evenly;
}
.conteneur {
display: flex;
flex-wrap: wrap;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-content: normal;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: normal
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: stretch;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: flex-start;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: flex-end;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: center;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: baseline;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: space-between;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: space-around;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
.conteneur {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: space-evenly;
}
.conteneur > * {
width: 3em;
flex-shrink: 0;
}
L’espacement entre les éléments peut être géré à l’aide de gap
:
.conteneur {
display: flex;
gap: 1em;
}
.conteneur {
display: flex;
gap: 1em 2em; /* row-gap column-gap */
}
.conteneur {
display: flex;
row-gap: 1em;
column-gap: 2em;
}
L’alignement peut être spécifié par élément :
.conteneur {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.conteneur > *:nth-child(even) {
align-self: stretch;
}
.conteneur > *:nth-child(2) {
align-self: center;
}
Il est possible de donner l’indice d’un élément dans son conteneur (0
par défaut) :
.conteneur {
display: flex;
justify-content: stretch;
}
.un {
order:-2
}
.deux, .trois {
order: 1;
}
.cinq {
order:-1
}
<div class="conteneur">
<div class="un">1</div>
<div class="deux">2</div>
<div class="trois">3</div>
<div class="quatre">4</div>
<div class="cinq">5</div>
</div>
~ petite musique d’ascenseur ~
Et la conception d’interface dans tout ça…
Position et taille initiales des éléments
La taille initiale des éléments est gérée par la propriété flex-basis
:
flex-basis: number | auto;
Si la taille du conteneur est plus grande :
Si la taille du conteneur est trop petite :
flex-shrink
flex-shrink
permet de modifier la quantité de réduction à appliquer à un élément (1
par défaut) :
.deux {
flex-shrink: 0
}
.un, .deux {
flex-shrink: 0
}
.un {
flex-shrink: 3
}
.deux {
flex-shrink: 2
}
flex-grow
flex-grow
permet de modifier la quantité de réduction à appliquer à un élément (0
par défaut) :
.deux {
flex-grow: 1
}
.deux {
flex-grow: 1
}
.trois {
flex-grow: 3
}
flex
flex
est un raccourci pour flex-grow
, flex-shrink
et flex-basis
:
flex: 0 1 auto;
flex: 1;
flex: 1 1 0;
body
Par défaut body
et html
ont leur hauteur définie pour l’affichage du contenu :
html, body {
height: 100%;
}
De plus, body
comporte par défaut des marges qui produisent l’apparition d’une barre de défilement :
html, body {
height: 100%;
margin: 0;
}
Permet l’ajout conditionnel de règles CSS en fonction :
Précise le type de périphérique, on dispose maintenant de all
(défaut), print
et screen
.
@media print {
...
}
@media print, screen {
...
}
@media all {
...
}
Précise une caractéristique :
aspect-ratio
max-width
min-width
orientation
prefers-color-scheme
resolution
@media screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}
@media (max-width: 600px) {
body {
background-color: lightblue;
}
}
Combinent plusieurs types ou caractéristiques :
and
,
not
only
@media screen and (min-width: 600px) and (max-width: 800px),
screen and (min-width: 1200px) {
body {
background-color: lightblue;
}
}
@media ( screen and (min-width: 600px) and (max-width: 800px) ),
( screen and (min-width: 1200px) ) {
body {
background-color: lightblue;
}
}
@media only screen and (min-width: 600px) {
body {
background-color: lightblue;
}
}
@media not screen and (min-width: 600px) {
body {
background-color: lightblue;
}
}
Modification structurelle de la page…
.page__main, .content__main {
display: flex;
flex-direction: column;
}
.page__main, .content__main {
display: flex;
flex-direction: column;
}
@media (min-width: 600px) and (max-width: 800px) {
.page__main {
flex-direction: row;
}
}
.page__main, .content__main {
display: flex;
flex-direction: column;
}
@media (min-width: 600px) and (max-width: 799px) {
.page__main {
flex-direction: row;
}
}
@media (min-width: 800px) {
.content__main {
flex-direction: row-reverse;
}
}
Le module « grid », est un modèle bidimensionnel permettant d’organiser les éléments d’un conteneur su une grille :
Mais surtout il permet d’agir sur chaque élément pour spécifier sa position et son étirement.
Le module n’est pas encore un standard officiel, mais son brouillon est actuellement supporté par la plupart des navigateurs.
Le module s’applique à un conteneur et ses éléments fils sont positionnés.
.conteneur {
display: grid; /* or inline-grid */
}
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>5</div>
</div>
Par défaut : une colonne occupant tout l’espace du conteneur et une ligne supplémentaire est générées pour chaque élément.
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>5</div>
</div>
.conteneur {
display: grid;
}
.conteneur {
display: grid;
grid-template-columns: 50px 100px;
}
.conteneur {
display: grid;
grid-template-columns: 50px 100px;
grid-template-rows: 30px 60px
}
les dimensions peuvent être définies par :
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>6</div>
</div>
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>long</div>
</div>
.conteneur {
display: grid;
grid-template-columns: 50px 3em 50px;
grid-template-rows: 2em 50%;
}
.conteneur {
display: grid;
grid-template-columns: 25px 1fr 2fr;
grid-template-rows: 3fr 1fr;
}
.conteneur {
display: grid;
grid-template-columns: 25px auto auto;
grid-template-rows: 25px auto;
}
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>7</div>
</div>
.conteneur {
display: grid;
grid-template-rows: 50px 50px;
grid-template-columns: 1fr 1fr;
}
.conteneur {
display: grid;
grid-template-rows: 50px 50px;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 30px;
}
.conteneur {
display: grid;
grid-template-rows: 50px 50px;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 30px;
grid-auto-flow: row;
}
.conteneur {
display: grid;
grid-template-columns: 50px 50px;
grid-template-rows: 1fr 1fr;
grid-auto-flow: column;
}
.conteneur {
display: grid;
grid-template-columns: 50px 50px;
grid-template-rows: 1fr 1fr;
grid-auto-flow: column;
grid-auto-columns: 30px;
}
.conteneur {
display: grid;
grid-template-rows: 1fr 1fr;
grid-auto-flow: column;
grid-auto-columns: 50px 80px;
}
CSS propose la fonction minmax(min, max)
pour intéragir avec les dimensions :
.conteneur {
display: grid;
grid-template-rows: minmax(18em, auto);
}
.conteneur {
display: grid;
grid-template-rows: minmax(auto, 50%);
}
CSS propose la fonction repeat(nb, size)
pour générer plusieurs dimentions identiques :
.conteneur {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, auto);
}
L’espacement entre les éléments peut être géré à l’aide de grid-row-gap
et grid-column-gap
:
.conteneur {
display: grid;
grid-template-columns: 1fr, 1fr;
grid-column-gap: 1em;
}
.conteneur {
display: grid;
grid-template-columns: 1fr, 1fr;
grid-row-gap: 1em;
}
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>6</div>
</div>
.conteneur {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.conteneur > *:first-child {
}
.conteneur > *:first-child {
grid-column-start: 2;
grid-row-start: 3;
}
.conteneur > *:first-child {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 3;
grid-row-end: 4;
}
.conteneur > *:first-child {
grid-column: 2;
grid-row: 3 / 4;
}
.conteneur > *:first-child {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 4;
}
.conteneur > *:first-child {
grid-area: 2 / 1 / 4 / 3;
}
<div class="conteneur">
<div>1</div>
<!-- ... -->
<div>6</div>
</div>
.conteneur {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
height: 100%;
}
.conteneur > *:nth-child(odd) {
grid-row: span 2;
}
La cascade est un algorithme de filtre et de tri :
!important
,Le CSS
div {
background-color: red;
}
div {
background-color: blue;
}
div.a {
background-color: red;
}
div {
background-color: blue;
}
div div {
background-color: red;
}
div {
background-color: blue;
}
Le HTML
<div>
<div class="a">bleu</div>
<div>bleu</div>
</div>
<div>
<div class="a">red</div>
<div>bleu</div>
</div>
<div>
<div class="a">red</div>
<div>red</div>
</div>
Sélecteurs | milliers | centaines | dizaines | unités |
---|---|---|---|---|
div.a | 1 | 1 | ||
div div.a | 1 | 2 | ||
#b .a | 1 | 1 |
Sélecteurs | milliers | centaines | dizaines | unités |
---|---|---|---|---|
div.a.b.c… | 26 | 1 | ||
#a | 1 |
ul {
}
button {
}
Trop générique
#page {
}
#page ul.menu {
}
#page ul.menu {
}
#page ul.menu li.menu-item {
}
#page ul.menu li.menu-item button {
}
Complexe à maintenir
Bonnes pratiques :
Avantages :
Avantages :
Avantages :
Avantages :
Avantages :
.menu
, .sub-header
, .input
..menu__item
, .sub-header__title
, .input__caption
..menu--highlighted
, .sub-header__title--small
, .input__caption--error
.Pour renforcer la réutilisation d’un Block : on évite de le positionner (position
, margin
, float
, …).
C’est le rôle du parent ou d’un Modificateur.
<header class=".header">
<button class="header__connection button">
Connection
</button>
</header>
.header {
position: relative;
background-color: #999;
}
.header__connection {
position: absolute;
top: 5px;
right: 5px;
}
.button {
border: 2px solid #78a;
}
Modification CSS à l’aide de JavaScript.
Pour accéder à des éléments de la page HTML :
const element = document.querySelector(".menu");
const element = document.querySelector(".header .button.connection");
const elements = document.querySelectorAll(".menu");
function clickHandle() {
console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.onClick = clickHandle;
function clickHandle() {
console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.addEventListener("click", clickHandle);
const element = document.querySelector(".menu .toggle-display");
element.onClick = function() {
console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.addEventListener("click", function() {
console.log("click");
});
onload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title></title>
<script src="js/scripts.js"></script>
<link rel="icon" href="images/favicon.png" />
</head>
<body>
...
</body>
</html>
window.addEventListener("load", function() {
const element = document.querySelector(".menu .toggle-display");
})
classlist
element = document.querySelector(".mon .selecteur");
element.classlist.add("uneClasse");
element.classlist.remove("uneClasse");
element.classlist.toggle("uneClasse");
element.classlist.contains("uneClasse");
element.classlist.replace("uneClasse", "uneAutreClasse");
window.addEventListener("load", function() {
const btnElt = document.querySelector(".menu .hide");
btnElt.addEventListener("click", function() {
contentElt = document.querySelector(".main .content");
contentElt.classlist.add("hide");
});
}
window.addEventListener("load", function() {
const btnElt = document.querySelector(".menu .show");
btnElt.addEventListener("click", function() {
contentElt = document.querySelector(".main .content");
contentElt.classlist.remove("hide");
});
}
window.addEventListener("load", function() {
const btnElt = document.querySelector(".menu .toggleDisplay");
btnElt.addEventListener("click", function() {
contentElt = document.querySelector(".main .content");
contentElt.classlist.toggle("hide");
if (contentElt.classlist.contains("hide")) {
btnElt.classlist.add("plus");
}
else {
btnElt.classlist.remove("plus");
}
});
}