28112 sujets

CSS et mise en forme, CSS3

Modérateur
Bonjour à tous,

Petite question sur la faisabilité d'interagir au hover (ou en ajoutant une class parente) sur un svg qui utilise use ?

J'ai fais un exemple d'un hamburger menu pour illustrer. On voit que sur le premier qui n'utilise pas use, pas de problème. Sur les deux autre, cela ne fonctionne pas. En inspectant, on voit le shadow dom qui insère le svg de base et je me pose la question de savoir si c'est accessible pour appliquer les transformations d'une manière ou d'une autre ?

Merci Smiley smile
Et bien justement c'est ça le problème avec les sprites SVG. C'est pourquoi il faut injecter le SVG inline dans ce cas. Voir les articles de css-tricks sur le sujet.
Modifié par Olivier C (17 Oct 2020 - 09:27)
Modérateur
Bonjour,

Si ça peut aider, voilà où j'en suis.

En théorie, ça devrait fonctionner mais ça marche plus ou moins bien selon les navigateurs (firefox semble le moins bogué).

Edit : ça semble bien marcher avec firefox (windows et mac os) et safari récent (mac os). Ça ne marche qu'à moitié avec chrome (partout) et edge (ils font bien les transforms, mais pas les transitions).

Edit (quelques explications) : l'idée est d'utiliser des variables css. Quand on change une variable css au niveau d'une balise <use>, ce changement est vu dans son shadow-root et hérité par toutes les balises qui s'y trouvent. Du coup, si on définit les valeurs des propriétés transform et opacity avec des variables css, et qu'on modifie la valeur de ces variables lors d'un hover sur le svg, ce changement est transmis aux éléments situés dans le shadow-root du <use> et l'effet se produit ... sauf que Chrome (et Edge) sont bogués en ce qui concerne la propriété transition.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>

body {
  display: flex;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  font-family: sans-serif;
}
body > * {
  margin: 0 1rem;
  text-align: center;
}

.d-none {
  display: none;
}

p {
  margin-bottom: 1rem;
  font-style: italic;
}

svg {
  width: 5rem;
  height: 5rem;
  fill: #C4C4C4;
  cursor: pointer;
  transition: fill .3s ease;
}

svg:hover, svg:focus {
  fill: #777;
  --t1:rotate(45deg);
  --t2:rotate(-45deg);
  --o:0;
  --tr1:translateY(calc(50% + 1px));
  --tr2:translateY(calc(-50% + 1px));
}
rect
{
	transition:transform .3s ease,opacity .1s ease;
}
rect:nth-of-type(1)
{
	transform:var(--tr1,none);
	opacity:var(--o,1);
}
rect:nth-of-type(2)
{
	transform:var(--t1,none);
	transform-origin:center;
	transition-delay:.3s;
}
rect:nth-of-type(3)
{
	transform:var(--t2,none);
	transform-origin:center;
	transition-delay:.3s;
}
rect:nth-of-type(4)
{
	transform:var(--tr2,none);
	opacity:var(--o,1);
}

</style>
</head>
<body>

<div class="svg-inline">
  <p>svg inline</p>
  <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" width="16" height="2" rx="1"></rect>
    <rect x="0" y="7" width="16" height="2" rx="1"></rect>
    <rect x="0" y="7" width="16" height="2" rx="1"></rect>
    <rect x="0" y="14" width="16" height="2" rx="1"></rect>
  </svg>
</div>

<div class="d-none svg-template">
  <p>svg template</p>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="hamburger" viewBox="0 0 16 16">
      <rect width="16" height="2" rx="1"></rect>
      <rect y="7" width="16" height="2" rx="1"></rect>
      <rect y="7" width="16" height="2" rx="1"></rect>
      <rect y="14" width="16" height="2" rx="1"></rect>
    </symbol>
  </svg>
</div>

<div class="svg-use">
  <p>svg use</p>
  <svg xmlns:xlink="http://www.w3.org/1999/xlink" class="icon" title="icon" data-icon-id="hamburger">
    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#hamburger"></use>
  </svg>
</div>

</body>
</html>

Amicalement,
Modifié par parsimonhi (17 Oct 2020 - 15:12)
J'ai retrouvé quelques articles auxquels je faisais allusion :
- Styling Inline SVG – Powers and Limitations
- SVG `symbol` a Good Choice for Icons

PS : Au fait bien vu le menu hamburger en SVG, c'est sans doute la solution la plus optimale aujourd'hui.

Par contre, pourquoi mettre le focus sur le SVG ? Ce dernier ne sera-t-il pas au sein d'un bouton ? En soit, juste avec le SVG, ça ne marche pas... (?)
button:focus svg {
  /* le code */
}

Modifié par Olivier C (17 Oct 2020 - 21:02)
Modérateur
Bonjour,
Olivier C a écrit :
J'ai retrouvé quelques articles auxquels je faisais allusion :
- Styling Inline SVG – Powers and Limitations
- SVG `symbol` a Good Choice for Icons


Tu peux jeter à la poubelle ta première référence "Styling Inline SVG – Powers and Limitations" (parsemée d'erreurs de code déjà). Heureusement, y en a un dans les commentaires qui a tenté de corriger le tir.

Je te conseille plutôt celui-là :
https://tympanus.net/codrops/2015/07/16/styling-svg-use-content-css/

Amicalement,
Modifié par parsimonhi (17 Oct 2020 - 23:32)
Modérateur
Ok merci les gars ! J'ai essayé d'accéder au shadow dom en lisant la doc mais pas réussi Smiley decu
La question du pourquoi le focus, c'était uniquement pour les tests (en vrai ça n'a pas de sens).
L'idée du svg inline dans le code ne va pas car le projet est basé sur la réusabilité et la manière dont on utilise les SVG sont externes (donc pas possible de changer à court terme) ? car on sait quand même modifier les couleurs et ça nous suffit pour 99.9% des usages.

Pour finir, même si ce n'est pas la meilleure idée, j'ai utilisé un simple `div>span*3` pour créer le menu.

Encore merci ! Smiley smile
De toute façon ton focus ne pouvait pas directement être appliqué sur ton SVG de démo car le SVG n'est pas un élément "focusable", c'est pour cette raison que tu verras presque toujours un bouton en wrapper dans les exemples en lignes (et aussi parce qu'un button(type='button') est approprié en html5 pour déclencher un comportement javascript prévisible).

Sinon, pour pousser le bouchon, tu peux aussi utiliser des pseudos éléments (ce que je faisais juste avant de passer à ton SVG). Un exemple sur cette page (seulement si responsive) : Scriptura
Modifié par Olivier C (20 Oct 2020 - 14:38)