⏰ CSS Clockworks
Safety Last - 1923
Speakers
I'm not a designer !
CSS is Awesome!
The Rule of Least Power suggests choosing the least powerful language suitable for a given purpose
-
Bien connaître les sélecteurs, et les unités
-
Évitez trop d'adhérences aux pré-processeurs
-
Les pseudo-éléments
::before
et::after
sont géniaux ! -
Les pseudo-classes comme
:checked
c'est puissant - Traitez le CSS comme du code !
- CSS is Awesome au Devfest Toulouse 2017
- Blog Making Of
Live-coding
Live-coding
Le cadre
.clock-step1 {
display: inline-block;
width: 1em;
height: 1em;
margin: .25em;
background: white;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
La cadre - liens
-
-
L'élément
<time>
existe !
-
-
currentColor
etem
peuvent être utilisés comme des variables.
Une aiguille
.clock-step2 {
position: relative;
display: inline-block;
width: 1em;
height: 1em;
margin: .25em;
background: white;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
/* pin */
.clock-step2::before {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
width: .02em;
height: .4em;
position: absolute;
top: 50%;
left: calc(50% - .01em);
}
Une aiguille - liens
-
On retrouve souvent le positionnement
absolute
avec les pseudo-éléments
La rotation
.clock-step3 {
position: relative;
display: inline-block;
width: 1em;
height: 1em;
margin: .25em;
background: white;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
/* pin */
.clock-step3::before {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
--width: .02em;
--height: .4em;
/* 37 minutes */
--angle: calc(.5turn + 1turn / 60 * 37);
width: var(--width);
height: var(--height);
position: absolute;
top: 50%;
left: calc(50% - var(--width) / 2);
transform: rotate(var(--angle));
transform-origin: top center;
}
La rotation - liens
-
Les custom properties sont héritées,
très utiles dans les Web Components avec le Shadow DOML'unité
turn
est souvent plus intuitive que les autres unités d'angles.
Heure et minutes
.clock-step4 {
position: relative;
display: inline-block;
width: 1em;
height: 1em;
margin: .25em;
background: white;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
/* pins */
.clock-step4::before, .clock-step4::after {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
width: var(--width);
height: var(--height);
position: absolute;
top: 50%;
left: calc(50% - var(--width) / 2);
transform: rotate(var(--angle));
transform-origin: top center;
}
/* hour pin */
.clock-step4::before {
--width: .035em;
--height: .2em;
--angle: calc(.5turn + 1turn / 12 * var(--hour));
}
/* minute pin */
.clock-step4::after {
--width: .02em;
--height: .3em;
--angle: calc(.5turn + 1turn / 60 * var(--minute));
}
Un peu de JavaScript
const currentTime = () => {
const now = new Date();
const h = now.getHours();
const min = now.getMinutes();
const sec = now.getSeconds();
return { h, min, sec };
};
// Set --hour, --minute and --second
const setHourMinuteSecond = (elt) => {
const { h, min, sec } = currentTime();
elt.style.setProperty("--hour", "" + h);
elt.style.setProperty("--minute", "" + min);
elt.style.setProperty("--second", "" + sec);
};
setHourMinuteSecond(document.body);
setInterval(() =>
setHourMinuteSecond(document.body),
1000); /* 1s */
La trotteuse
.clock-step5 {
position: relative;
display: inline-block;
width: 1em;
height: 1em;
margin: .25em;
background: white;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
/* pins */
.clock-step5 .pin {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
width: var(--width);
height: var(--height);
position: absolute;
top: 50%;
left: calc(50% - var(--width) / 2);
transform: rotate(var(--angle));
transform-origin: top center;
border: .001em solid rgba(0, 0, 0, .15);
box-shadow: 0 0 .005em rgba(0, 0, 0, .25);
}
.clock-step5 .pin::before,
.clock-step5 .pin::after {
position: absolute;
display: block;
content: '';
background-color: inherit;
border-radius: 50%;
}
.clock-step5 .pin::before {
width: calc(2 * var(--width));
height: calc(2 * var(--width));
top: calc(-1 * var(--width));
left: calc(-.5 * var(--width));
}
.clock-step5 .pin::after {
width: 100%;
height: calc(2 * var(--width));
top: calc(-2 * var(--width));
}
/* hour pin */
.clock-step5 .pin.hourhand {
color: gray;
--width: .035em;
--height: .2em;
--angle: calc(.5turn + 1turn / 12 * var(--hour));
}
/* minute pin */
.clock-step5 .pin.minutehand {
color: silver;
--width: .02em;
--height: .3em;
--angle: calc(.5turn + 1turn / 60 * var(--minute));
}
/* second pin */
.clock-step5 .pin.secondhand {
--width: .015em;
--height: .4em;
--angle: calc(.5turn + 1turn / 60 * var(--second));
}
La trotteuse - liens
-
Les fonctions trigonometriques du CSS ne sont pas encore disponibles
-
On peut utiliser un pre-processeur, ou du JS, pour remplacer ces fonctions
🤓 Ou les formules Taylor / Maclaurin avec des custom properties, voir cet exemple.
Les animations
.clock-step6 {
position: relative;
background: white;
display: block;
width: 1em;
height: 1em;
margin: .25em;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
}
/* pins */
@keyframes rotatePin {
from {
transform: rotate(.5turn);
}
to {
transform: rotate(1.5turn);
}
}
.clock-step6 .pin {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
width: var(--width);
height: var(--height);
position: absolute;
top: 50%;
left: calc(50% - var(--width) / 2);
transform-origin: top center;
border: .001em solid rgba(0, 0, 0, .15);
box-shadow: 0 0 .005em rgba(0, 0, 0, .25);
animation: rotatePin var(--duration) linear infinite;
/* animation-play-state: paused; */
--delay : calc(
var(--second) +
60 * var(--minute) +
3600 * var(--hour)
);
animation-delay: calc(-1s * var(--delay));
}
.clock-step6 .pin::before,
.clock-step6 .pin::after {
position: absolute;
display: block;
content: '';
background-color: inherit;
border-radius: 50%;
}
.clock-step6 .pin::before {
width: calc(2 * var(--width));
height: calc(2 * var(--width));
top: calc(-1 * var(--width));
left: calc(-.5 * var(--width));
}
.clock-step6 .pin::after {
width: 100%;
height: calc(2 * var(--width));
top: calc(-2 * var(--width));
}
/* hour pin */
.clock-step6 .pin.hourhand {
color: gray;
--width: .035em;
--height: .2em;
--duration: calc(60s * 60 * 12);
}
/* minute pin */
.clock-step6 .pin.minutehand {
color: silver;
--width: .02em;
--height: .3em;
--duration: calc(60s * 60);
}
/* second pin */
.clock-step6 .pin.secondhand {
--width: .015em;
--height: .4em;
--duration: 60s;
}
Les animations - liens
Les marqueurs
.clock-step7 {
position: relative;
background: white;
display: block;
width: 1em;
height: 1em;
margin: .25em;
border: .05em solid currentColor;
box-sizing: border-box;
border-radius: 50%;
box-shadow:
.05em .05em .1em rgba(0, 0, 0, .5),
inset 0 0 0 .02em white,
inset .05em .05em .1em rgba(0, 0, 0, .5),
inset .5em .5em 1em rgba(0, 0, 0, .1);
counter-reset: tick;
}
/* pins */
@keyframes rotatePin {
from {
transform: rotate(.5turn);
}
to {
transform: rotate(1.5turn);
}
}
.clock-step7 .pin {
background: currentColor;
border-bottom-left-radius: 100% 80%;
border-bottom-right-radius: 100% 80%;
content: '';
width: var(--width);
height: var(--height);
position: absolute;
top: 50%;
left: calc(50% - var(--width) / 2);
transform-origin: top center;
border: .001em solid rgba(0, 0, 0, .15);
box-shadow: 0 0 .005em rgba(0, 0, 0, .25);
animation: rotatePin var(--duration) linear infinite;
/* animation-play-state: paused; */
--delay : calc(
var(--second) +
60 * var(--minute) +
3600 * var(--hour)
);
animation-delay: calc(-1s * var(--delay));
}
.clock-step7 .pin::before,
.clock-step7 .pin::after {
position: absolute;
display: block;
content: '';
background-color: inherit;
border-radius: 50%;
}
.clock-step7 .pin::before {
width: calc(2 * var(--width));
height: calc(2 * var(--width));
top: calc(-1 * var(--width));
left: calc(-.5 * var(--width));
}
.clock-step7 .pin::after {
width: 100%;
height: calc(2 * var(--width));
top: calc(-2 * var(--width));
}
/* hour pin */
.clock-step7 .pin.hourhand {
color: gray;
--width: .035em;
--height: .2em;
--duration: calc(60s * 60 * 12);
}
/* minute pin */
.clock-step7 .pin.minutehand {
color: silver;
--width: .02em;
--height: .3em;
--duration: calc(60s * 60);
}
/* second pin */
.clock-step7 .pin.secondhand {
--width: .015em;
--height: .4em;
--duration: 60s;
}
/* Ticks */
.clock-step7 .tick {
position: absolute;
top: 50%;
left: 50%;
height: .4em;
transform-origin: top center;
--angle: calc(.5turn + 1turn / 12 * var(--count));
transform: rotate(var(--angle));
counter-increment: tick;
}
.clock-step7 .tick::before {
position: absolute;
display: block;
font-size: 8%;
top: calc(100% - .8em);
transform: translateX(-40%) rotate(.5turn);
text-align: center;
content: counter(tick, upper-roman);
}
.clock-step7 .tick {
opacity: .25;
}
.clock-step7 .tick:nth-child(3n) {
opacity: .8;
}
Les marqueurs - liens
-
@counter-style
(que sur Firefox)
Support
Support
Ça marche partout
-
currentColor
,border-radius
,box-shadow
,box-sizing
, -
CSS Generated content for pseudo-elements,
calc
, -
CSS3 2D Transforms, CSS Animation
Rappel Accessibilité
-
Utilisateurs de IE 11 en France: 0,84%
-
Personnes atteintes d'un trouble de la vision en France: 2,5%
-
Rendre accessibles vos sites c'est traiter ces 2 situations
-
️ Revoyez vos priorités ❗️
Conclusion
Conclusion
À quoi ça sert ?
-
À rien.
Les moments 'WTF'
Pourquoi en est on là ?
-
🕳
Incompatibilité -
📄
Documentationvoir MDN -
⌛️ Pas le temps sur les projets
-
🚫 pas de cours CSS
-
😡 technologie mésestimée
-
🛑 Il faut changer cela !
Comment apprendre
-
🤹♀️️ regardez des présentations 🤹♂️
-
🎓 mentoring
-
📚 livres, par exemple CSS Secrets
-
... les side-projects
- Maximiser `(wow)/(wtf)`
Passé, présent et future
-
🔮 Que sera le web demain ?
-
Lorsque tu ne sais pas où tu vas, regarde d'où tu viens.
-
🧱 Donnez-vous du temps pour les bases: HTML, CSS, JS
Merci
-
Questions ?
- (les retours sont bienvenus)