28182 sujets

CSS et mise en forme, CSS3

Bien le bonjour à tous,

Maintenant que les éléments HTML <details> / <summary> sont devenus accessibles sur tous les navigateurs j'aimerais remplacer mes anciennes astuces uniquement avec ces éléments HTML, appuyé essentiellement avec du CSS, éventuellement avec un peu de JavaScript pour certaines fonctionnalités mineures, mais pas plus.

Mes "anciennes astuces" reposaient déjà sur des éléments <details> / <summary>, mais mon JS les remplaçaient intégralement. L'idée ici serait désormais de préserver le HTML d'origine. Le pire c'est que j'ai vu passer une page qui me semblait remplir le contrat mais, argh !, je l'ai laisser filer entre mes doigts sans la bookmarker...

Je vais donc tenter quelque chose prochainement, mais si vous avez une idée de ressource avant que je me colle à réinventer la roue à nouveau, je suis preneur.
Modifié par Olivier C (09 Dec 2024 - 14:00)
Je me rends compte que je n'ai pas été explicite. Voici un HTML pour l'exemple :
<div class="tabs">
  <details name="test" open>
    <summary>Onglet 1</summary>
    <div class="pannel">Contenu de l'onglet 1</div>
  </details>
  <details name="test">
    <summary>Onglet 2</summary>
    <div class="pannel">Contenu de l'onglet 2</div>
  </details>
  <details name="test">
    <summary>Onglet 3</summary>
    <div class="pannel">Contenu de l'onglet 3</div>
  </details>
</div>

Il faut que tous les <summary> soient distribués à la suite, en ligne, et les div.pannel, eux, doivent occuper une même ère en dessous des summarys.

Je pense que l'on doit pouvoir faire ça avec Grid Layout.
Modifié par Olivier C (09 Dec 2024 - 00:41)
Administrateur
Hello,

Pour le coup, je ne suis pas sûr que ce soit vraiment le job de details/summary (mais je me trompe peut-être).

Les Patterns ARIA ne l'évoquent pas (mais ne sont peut-être plus à jour) : https://www.w3.org/WAI/ARIA/apg/patterns/tabs/

L'exemple concret : https://codepen.io/pen

EDIT : après quelques essais infructueux, je suis tombé sur une discussion qui semble dire que "c'est un peu tordu" avec details/summary : https://stackoverflow.com/questions/71985292/details-tag-with-grid-elements-in-summary-and-content
Bonsoir Raphaël,

Les spécifications du W3C je les connais, je m'étais appuyé dessus il y a 2 ans pour recréer mes composants. Quand à <details> / <summary> il posait un problème d'accessibilité à une époque car <summary> était en display:none, mais c'est résolut depuis et c'est pourquoi je me penche à nouveau sur la question.

Je ne péterai pas trop crédit à la discussion que tu évoques sur StackOverflow : leurs solutions c'est juste pas possible. De toute façon ils ne sont pas notés.

Je vais voir...
Modérateur
Bonjour,

Il me semble que vu que chaque balise <details> encapsule son contenu, une grid css sur une de ces balises ne concernera que le contenu de chacune de ces balises, et une grid css sur un éventuel conteneur englobant tous ces balises <details> ne concernera pas les balises se trouvant à l'intérieur de chaque balise <details>.

On ne peut donc pas espérer par exemple donner la même hauteur à tous les <summary> en misant sur le fait qu'une grid où qu'elle soit positionnerait tous les <summary> sur sa première ligne.

Amicalement,
@parsimonhi : c'est pourquoi je comptais utiliser display: contents; sur les <details>.
Je ne sais pas encore trop hein, une idée comme ça...
Modifié par Olivier C (08 Dec 2024 - 23:10)
Modérateur
Bonjour
Olivier C a écrit :
@parsimonhi : c'est pourquoi je comptais utiliser display: contents; sur les <details>.
Je ne sais pas encore trop hein, une idée comme ça...

Je n'ai jamais utilisé display: contents; donc je ne saurais dire a priori si c'est prometteur ou pas. Mais ça me semble une piste intéressante.

Note que le support de cette propriété semble en 2024 encore assez inégal : https://caniuse.com/css-display-contents

Amicalement,
Oui c'est vrai, mais je trouve que c'est déjà assez bien supporté pour les besoins que j'en ai.

Pour vous donner une idée de ce que je cherche à faire :
.tabs {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    'tablist'
    'pannels';
  
  & details {
    display: contents;

    & summary {
      grid-area: tablist;
      padding: .5em 1em;
      background-color: #eee;
      cursor: pointer;
    }
      
    & .pannel {
      grid-area: pannels;
      padding: .5em 1em;
      background-color: #eee;
    }
    
    &[open] {
      & summary {
        pointer-events: none;
      }
    }
  }
}

Dans ce code tous les onglets se superposent, il faut que je trouve un moyen de les disposer côte à côte, sans valeurs en dur, bien évidement.
Modifié par Olivier C (09 Dec 2024 - 00:43)
\ô/
j'avais fait quelque chose de similaire et étais arrivé au CSS suivant :
.tabs {
  display: flex;
  position: relative;
  min-height: 23em;
  background-color: #FFF;
}
details summary {
  display: block;
  z-index: 1;
  position: relative;
  height: 3em;
  padding: 0 2em;
  border: 1px solid #888;
  border-radius: 15px 15px 0 0;
  font-size: 1.25rem;
  font-weight: bold;
  line-height: 3;
  background-color: #F5F5F5;
  cursor: pointer;
}
details[open] {
  pointer-events: none;
}
details[open] summary {
  border-bottom: none;
  background-color: #FFF;
  transform: scale(1,1.05);
}
details .pannel {
  z-index: 0;
  position: absolute;
  right: 0;
  left: 0;
  box-sizing: border-box;
  margin: 0;
  padding: 1em;
  max-height: 20em;
  min-height: 20em;
  border: 1px solid #888;
  overflow-y: auto;
  background-color: #FFF;
  pointer-events: auto;
}

Le positionnement en absolu forçant à définir une hauteur aux éléments, cela peut être une base !
Modérateur
Bonjour/bonsoir,

Il n'y a quasiment que Firefox encore capable d'appliquer display:contents; sur détails, Chrome ne le permet plus, peut-être ne l'a t'il jamais permis, souvenirs incertains.

Cela à peut-être un lien avec un défaut d'accessibilité au clavier, qui pourrait néanmoins être compensé avec l'attribut tabindex (ou javascript ...).
Chrome à aussi tendance à être compliqué avec les display en grille ou autre rendu (masonry, line-clamp, ...) juste une réflexion personnelle.

Voici un exemple encore fonctionnel avec Firefox https://codepen.io/gc-nomade/pen/MYgyxrK mais je pense que c'est une piste sans issues. Smiley bad

Ceci étant, display grid permet de modifier l'affichage d'une structure HTML en la transformant en boite à onglet.
Un conteneur avec une série de titres et divs se suivant, ne devraient pas perdre de sens (peut-être éviter CSS order quand-même). Exemple pour illustrer et tester mon propos: https://codepen.io/gc-nomade/pen/PwYNLXg
C'est peut-être aussi une piste intéressante mais un peu alambiqué en l'état avec des :not(:has(+:focus)) pour ne pas perdre le focus d'un onglet ouvert en cliquant Smiley rambo dedans ! Smiley smile

Cdt
Meilleure solution
Modérateur
Bonjour,

Je viens de faire quelques tests avec des <details> ayant display: contents et un conteneur englobant les balises <details> ayant un display: grid. Ça m'a l'air un peu bogué (ou alors je n'ai pas eu de bol).

Par exemple considérons le html suivant (3 balises <details> dans une balise <main> qui joue le rôle du container) :
<main class="container">
  <details>
    <summary class="L1C1">AA</summary>
    <p class="L2C1">Contenu AA</p>
  </details>
  <details>
    <summary class="L1C2">BB</summary>
    <p class="L2C2">Contenu BB</p>
  </details>
  <details>
    <summary class="L3C1">CC</summary>
    <p class="L4C1">Contenu CC</p>
  </details>
</main>

On souhaite afficher les deux premières balises <détails> côté à côte horizontalement, et la troisième balise <details> en dessous (cas plus général : on affiche autant de balises <details> côte à côte horizontalement que l'on peut, et on passe à la ligne dès qu'on a plus assez de place). On utilise le css suivant (on n'y met aucune bizarrerie volontairement) :
.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr auto 1fr auto;
}
.container > * {
  display: contents;
}
.container > * > * {
  border: 0.25em solid #000;
  color: #fff;
  margin: 0.25em;
}
.L1C1 {
  grid-row: 1;
  grid-column: 1;
  background: #900;
}
.L1C2 {
  grid-row: 1;
  grid-column: 2;
  background: #090;
}
.L2C1 {
  grid-row: 2;
  grid-column: 1;
  background: #600;
}
.L2C2 {
  grid-row: 2;
  grid-column: 2;
  background: #060;
}
.L3C1 {
  grid-row: 3;
  grid-column: 1;
  background: #009;
}
.L4C1 {
  grid-row: 4;
  grid-column: 1;
  background: #006;
}

Quand on déplie les <details>, avec Firefox et Safari, ça marche sans surprise. Mais avec Chrome, le contenu de la dernière balise <details> vient s'afficher sur la colonne d'à côté de son <summary> au lieu de s'afficher en dessous de son <summary>.

Un petit jsfiddle pour tester : https://jsfiddle.net/parsimonhi/c8qfy5wL/

On devrait peut-être pouvoir contourner ce problème, mais il y en a probablement d'autres, le problème que je viens de décrire étant apparu dès mon premier test. Un peu pénible a priori.

Note : si on remplace les balises <details> et <summary> par des <div>, ça marche comme attendu sur les 3 navigateurs.

Amicalement,
Je vous remercie chaleureusement pour toutes vos réponses. Je crois que GCyrillus a soulevé très clairement le point clé du problème - confirmé par Parsimonhi -, je l'avais vu moi aussi mais j'espérais me tromper : le fait que la balise <details> n'est que partiellement neutralisée par la règle display:contents, ce qui, de fait, limite les possibilités de mise en page des items restants avec Grid Layout.

Le pire c'est que je dev' avec Chrome : certains de mes prototypes étaient sans doute compatibles avec Firefox et j'aurais vu alors le poteau rose plus rapidement... Enfin bref, je vais donc rester avec mon ancien composant.

Merci encore à tous.
Modifié par Olivier C (10 Dec 2024 - 13:54)