28111 sujets

CSS et mise en forme, CSS3

Modérateur
Hello les gars,

J'aurais besoin d'un petit coup de pouce, je ne trouve pas la solution magique avec Grid pour arriver à mes fins.

Le problème :
Sur base de ce très simple HTML (je suis flexible si on veut le structurer différemment mais j'aimerais autant que possible le garder simple).
<dl>
  <dt>Key</dt>
  <dd>Value</dd>
  <dt>Key</dt>
  <dd>Value</dd>
  <dt>Key</dt>
  <dd>Value</dd>
</dl>

J'aimerais avoir un affichage automatique Key/Value soit sur la même ligne si l'espace le permet soit si un élément est trop long, les avoirs tous en 2 lignes. Donc soit :

Key                                       Value
--
Key                                       Value
--
Key                                       Value

ou si l'espace ne le permet pas :

Key
Value
--
Key
Value
--
Key
Value


La contrainte, je ne connais pas la taille de mon container donc c'est pour cela que je pensais à CSS Grid et un auto-fit (et un minmax avec max-content comme valeur).
Dernière chose, c'est que je ne veux pas avoir deux (ou plus) Key/Value sur une même ligne.

Ce n'est qu'une ligne de code à trouver mais je bloque dessus. Toute aide sera la bienvenue Smiley smile

Merci !
Modérateur
Bonsoir,

repeat(auto-fill,minmax(max-content,50%) ; devrait faire le travail pour un maintient en deux colonnes, mais le passage de deux à une colonne ne se fera pas .

Flex est peut-être plus flexible ici.

ex:
dl {
  display: flex;
  flex-wrap: wrap;
}
dt,
dd {
  margin: 0;
  box-sizing:border-box;
  padding: 0;
  border: 1px solid;
  min-width: 50%;
  flex-grow: 1;
}


Et pour distinguer les paires éventuellement :
dl>:nth-child(4n),dl>:nth-child(4n - 1) {background:gray;}


Ce n'est pas tout a fait ce que souhaites. Smiley decu

Cdt
Je partirai plutôt sur du flex.
Le problème de ton HTML c'est qu'il n'établit pas de lien entre la clé et la valeur. On risque de se retrouver avec une clé sur la même ligne que la valeur précédente.
Je le modifierai comme ça :
<dl>
   <div class="kw">
      <dt>Très longue key - Très longue key - Très longue key - Très longue ...</dt>
      <dd>Value</dd>
   </div>
   <div class="kw">
      <dt>Key</dt>
      <dd>Value</dd>
   </div>
   <div class="kw">
      <dt>Key</dt>
      <dd>Value</dd>
   </div>
</dl>


Et le CSS :

.kw {display:flex; flex-flow:wrap;}
dt {flex:1 0 1fr; min-width:48%; margin:1%;}
dd {flex:1 0 1fr; min-width:48%; margin:1%;}
Modérateur
Hello,
Merci pour vos réponses, j'aime l'idée.
Ceci dit si je peux ajouter une contrainte qui n'était pas super clair. J'aimerais (dans l'idéal) n'avoir rien à faire entre une version ou l'autre). Si il y a une clé qui dépasse et qu'une valeur passe passe à la ligne, j'aimerais que le style soit le même pour toutes les lignes et éviter d'avoir un mix d'affichage.


ps : Alainpre, je n'ai jamais vu que l'on puisse utiliser l'unité fr avec autre chose que grid. Pouvons-nous ? Smiley sweatdrop
Modifié par Yordi (27 Mar 2020 - 14:32)
Modérateur
Pour l'effet rechercher, tu vas avoir besoin de l'appui de javascript et de flex.

L'idée est de se servir de flex , pouvoir mettre une largeur minimale et de forcer l’élément à s'étirer au maximum: grosso modo : min-width:40%; flex-grow:1; va mettre deux éléments cote à cote en utilisant le maximum d'espace disponible à parts égales (margin,padding et bordures ne poserons pas de problémes sauf valeurs extrémes et espaces d'affichage extrêmement réduits; => probabilité très faible + au delà de 33.33% , il n'y aura pas plus de 2 éléments)

si la boite en flex autorise le passage à la ligne (pil poil ton besoin) , il reste à vérifier la position de chaque dd par rapport à la gauche de son parent (dl) , si l'un d'entre eux est à gauche, alors il suffit de repasser dl en block ou tous les dd ou dt en width : 100%. CSS ne peut le faire mais c'est un job pour javascript:

Exemple: https://codepen.io/gc-nomade/pen/MWwZowz
HTML
<dl>
  <dt>Keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy</dt>
  <dd>Valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee</dd>
  <dt>Key</dt>
  <dd>Value</dd>
  <dt>Key</dt>
  <dd>Value</dd>
    <dt>Key</dt>
  <dd>Value</dd>
  <dt>Key</dt>
  <dd>Value</dd>
    <dt>Key</dt>
  <dd>Value</dd>
  <dt>Key</dt>
  <dd>Value</dd>
</dl>


CSS


dl {
  display: flex;
  flex-wrap: wrap;
}
dt,
dd {
  margin: 0;
  box-sizing: border-box;
  padding: 0;
  border: 1px solid;
  min-width: 50%;
  flex-grow: 1;
}
dl > :nth-child(4n),
dl > :nth-child(4n - 1) {
  background: gray;
}

JavaScript
window.onload = check();
window.onresize = function () {
  check();
};
function check() {
  var flexPos = 50; // anyting more tha paddiing,margin and border
  var childPos;
  document.querySelector("dl").style.display = "flex";
  var parent = document.querySelector("dl");
  for (let child of document.querySelectorAll("dd")) {
    pos = child.offsetLeft;
    if (pos < flexPos) {
      childPos = pos;
    }
  }
  var parentPos = parent.offsetLeft;
  var childOffset = childPos - parentPos;
  if (childOffset == 0) {
    document.querySelector("dl").style.display = "block";
  }
}

Modifié par gcyrillus (28 Mar 2020 - 14:04)
Modérateur
Alainpre a écrit :
Je partirai plutôt sur du flex.
Le problème de ton HTML c'est qu'il n'établit pas de lien entre la clé et la valeur. On risque de se retrouver avec une clé sur la même ligne que la valeur précédente.
Je le modifierai comme ça :
&lt;dl&gt;
   &lt;div class="kw"&gt;
      &lt;dt&gt;Très longue key - Très longue key - Très longue key - Très longue ...&lt;/dt&gt;
      &lt;dd&gt;Value&lt;/dd&gt;
   &lt;/div&gt;
   &lt;div class="kw"&gt;
      &lt;dt&gt;Key&lt;/dt&gt;
      &lt;dd&gt;Value&lt;/dd&gt;
   &lt;/div&gt;
   &lt;div class="kw"&gt;
      &lt;dt&gt;Key&lt;/dt&gt;
      &lt;dd&gt;Value&lt;/dd&gt;
   &lt;/div&gt;
&lt;/dl&gt;


Et le CSS :

.kw {display:flex; flex-flow:wrap;}
dt {flex:1 0 1fr; min-width:48%; margin:1%;}
dd {flex:1 0 1fr; min-width:48%; margin:1%;}


Pour le flex , 100% d'accord.

Pour un div enfant de dl, pas d'accord Smiley decu

1fr ?? heu quelle idée hors contexte du modèle GRID ? flex-grow:1; fonctionne parfaitement en FLEX

Voici ce que je propose a @Yordi avec une touche JavaScript à coté de flex : https://codepen.io/gc-nomade/pen/MWwZowz

Cdt
Modifié par gcyrillus (27 Mar 2020 - 22:31)
Bonjour
Je pense que le code peut être simplifié

function check() {
  let oDl = document.querySelector("dt");
  document.querySelector("dl").classList.remove("incolumn");
  for (let oChild of document.getElementsByTagName("dd")) { 
    if(oChild.offsetLeft == oDl.offsetLeft){
      //il y a au moins un dd à la ligne
      document.querySelector("dl").classList.add("incolumn");
      break;
    }
  }  
}

dl.incolumn {
  display : block
}
Yordi a écrit :
Hello,
ps : Alainpre, je n'ai jamais vu que l'on puisse utiliser l'unité fr avec autre chose que grid. Pouvons-nous ? Smiley sweatdrop


Cela fonctionne mais ce n'est pas officiel. Je pensais avoir lu ça quelque part en mais je viens de faire une rapide recherche et je ne retrouve pas. Donc à éviter sans doute.
De toute façon, comme le fait remarquer gcyrillus, flex-grow est préférable.

J'aurais aimé trouver une solution sans JS mais ta dernière contrainte complique les choses.
Administrateur
Alainpre a écrit :
Cela fonctionne mais ce n'est pas officiel. Je pensais avoir lu ça quelque part en mais je viens de faire une rapide recherche et je ne retrouve pas. Donc à éviter sans doute.

Hello,

Cette source m'intéresse aussi. Selon les specs et différents tests que j'ai pu faire, cette unité ne fonctionne que dans Grid Layout.
Dans Flexbox elle serait très exactement l'équivalent de flex: 1 comme disait gcyrillus, soit une base de zéro et un grow+shrink autorisés.