web-dev-qa-db-fra.com

Quel est le problème avec l'alignement vertical: ligne de base?

Je pensais que je connaissais bien le CSS, mais je devais expliquer quelque chose à quelqu'un tout à l'heure et j'ai trouvé que je ne pouvais pas.

Ma question se résume essentiellement à: pourquoi vertical-align:baseline Est-il ignoré alors qu'il y a d'autres alignements sur la même ligne?

Exemple: si la deuxième travée a vertical-align:bottom, L'alignement vertical de la première travée est ignoré s'il s'agit de baseline; il se comporte comme s'il avait bottom aussi.

span:first-child {vertical-align:baseline}
span:last-child {font-size:3em; vertical-align:bottom;}
<p>
  <span>one</span> <span>two</span>
</p>

Alors que si toutes les plages ont un alignement vertical autre que baseline, ou, si elles sont toutes baseline, elles se comportent comme prévu.

span:first-child {vertical-align:top}
span:last-child {font-size:3em; vertical-align:bottom;}
<p>
  <span>one</span> <span>two</span>
</p>
span:first-child {vertical-align:baseline}
span:last-child {font-size:3em; vertical-align:baseline;}
<p>
  <span>one</span> <span>two</span>
</p>

S'il s'agit d'un comportement normal, pourquoi n'est-il décrit nulle part? Je n'ai trouvé aucune source qui dit que la ligne de base et le haut/bas interfèrent l'un avec l'autre de cette manière.

28
Mr Lister

Vertical-Align

vertical-align est utilisé pour aligner éléments de niveau en ligne . Ce sont des éléments dont la propriété display est évaluée à:

  • inline
  • inline-block
  • inline-table (Non pris en compte dans cette réponse)

Les éléments de niveau en ligne sont disposés côte à côte en lignes. Une fois qu'il y a plus d'éléments qu'il n'y en a dans la ligne actuelle, une nouvelle ligne est créée en dessous. Toutes ces lignes ont une boîte de ligne dite , qui renferme tout le contenu de sa ligne. Un contenu de taille différente signifie des boîtes de ligne de hauteur différente.

Dans l'illustration suivante, les cases supérieure et inférieure des lignes sont indiquées par des lignes rouges.enter image description here

À l'intérieur de ces zones de ligne, la propriété vertical-align Est responsable de l'alignement des éléments individuels.

Référence

Le point de référence le plus important à aligner verticalement est la ligne de base des éléments impliqués. Dans certains cas, les bords supérieur et inférieur de la boîte englobante de l'élément deviennent également importants.

Éléments en ligne

enter image description here

Le bord supérieur et inférieur de la hauteur de ligne est indiqué par des lignes rouges, la hauteur de la police par des lignes vertes et la ligne de base par une ligne bleue.

À gauche , le texte a une hauteur de ligne définie à la même hauteur que la taille de police. La ligne verte et rouge s'est effondrée en une ligne de chaque côté.

Au milieu , la hauteur de la ligne est deux fois plus grande que la taille de la police.

À droite , la hauteur de la ligne est la moitié de la taille de la police.

Notez que les bords extérieurs de l'élément en ligne (les lignes rouges) n'ont pas d'importance, si la hauteur de la ligne est inférieure à la hauteur de la police.

Élément Inline-Block

enter image description here

De gauche à droite vous voyez:

  • un élément inline-block avec in-flow content

  • un élément inline-block avec in-flow contenu et overflow: hidden

  • un élément inline-block sans in-flow contenu (mais la zone de contenu a une hauteur)

Les limites de la marge sont indiquées par des lignes rouges, la bordure est jaune, le remplissage vert et la zone de contenu bleu. La ligne de base de chaque élément inline-block Est représentée par une ligne bleue.

La ligne de base de l'élément inline-block Dépend du contenu de l'élément in-flow . En cas de:

  • in-flow content la ligne de base de l'élément inline-block est la ligne de base du dernier élément de contenu dans le flux normal ( exemple à gauche)

  • in-flow content mais une propriété overflow évaluant autre chose que visible, la ligne de base est le bord inférieur de la zone de marge ( exemple au milieu)

  • no in-flow content la ligne de base est, encore une fois, le bord inférieur de la zone de marge ( exemple à droite)

Boîte de ligne

enter image description here

C'est probablement la partie la plus déroutante lorsque vous travaillez avec vertical-align. Cela signifie que la ligne de base est placée là où elle doit être pour remplir toutes les autres conditions telles que vertical-align Et en minimisant la hauteur de la zone de ligne. C'est un paramètre libre dans l'équation.

Étant donné que la ligne de base de la zone de ligne est invisible, il n'est pas toujours évident de savoir où elle se trouve. Mais, vous pouvez le rendre visible très facilement. Ajoutez simplement un caractère au début de la ligne dans les questions, comme le "x" sur la figure. Si ce personnage n'est aligné d'aucune façon, il se trouvera par défaut sur la ligne de base.

Autour de sa ligne de base, la zone de ligne a ce que l'on pourrait appeler sa zone de texte (lignes vertes sur la figure). La zone de texte peut simplement être considérée comme un élément en ligne à l'intérieur de la zone de ligne sans aucun alignement. Sa hauteur est égale au font-size De son élément parent. Par conséquent, la zone de texte entoure uniquement le texte non formaté de la zone de ligne. Comme cette zone de texte est liée à la ligne de base, elle se déplace lorsque la ligne de base se déplace.

Fragment

Si vous voulez faire des essais avec divers vertical-align Et font-size Ici, vous avez un extrait où vous pouvez l'essayer. Est également disponible en JSFiddle .

let sl1 = document.getElementById('sl1');
let sl2 = document.getElementById('sl2');
let sl3 = document.getElementById('sl3');
let sl4 = document.getElementById('sl4');
let Elm1 = document.getElementById('Elm1');
let Elm2 = document.getElementById('Elm2');
let Elm3 = document.getElementById('Elm3');
let Elm4 = document.getElementById('Elm4');
let ip1 = document.getElementById('ip1');
let ip2 = document.getElementById('ip2');
let ip3 = document.getElementById('ip3');
let ip4 = document.getElementById('ip4');
let slArr = [sl1, sl2, sl3, sl4];
let elmArr = [Elm1, Elm2, Elm3, Elm4];
let ipArr = [ip1, ip2, ip3, ip4];
let valueArr = ['baseline', 'top', 'middle', 'bottom'];
for (let i = 0; i < slArr.length; i++) {
  slArr[i].addEventListener('change', (event) => {
    elmArr[i].style.verticalAlign = event.target.value;
    elmArr[i].innerHTML = event.target.value;
    addDiv();
  })
}
for (let i = 0; i < ipArr.length; i++) {
  ipArr[i].addEventListener('change', (event) => {
    elmArr[i].style.fontSize = event.target.value + 'em';
    addDiv();
  })
}

document.getElementById('btnRandom').addEventListener('click', () => {
  for (let i = 0; i < elmArr.length; i++) {
    let element = elmArr[i];
    let fontSize = Math.floor(Math.random() * 4 + 1);
    ipArr[i].value = fontSize;
    element.style.fontSize = fontSize + 'em';
    let styleIndex = Math.floor(Math.random() * 4);
    element.style.verticalAlign = valueArr[styleIndex];
    element.innerHTML = valueArr[styleIndex];
    slArr[i].selectedIndex = styleIndex;
  }
}, this);

function addDiv() {
  let view = document.getElementById('viewer');
  view.innerHTML = "";
  elmArr.forEach(function(element) {
    let div = document.createElement('div');
    div.appendChild(element.cloneNode());
    view.appendChild(div);
  }, this);
}
.header span {
  color: #000;
}

select {
  width: 100px;
}

#elms {
  border: solid 1px #000;
  margin-top: 20px;
  position: relative;
}

span {
  color: #FFF;
  font-size: 1em;
}

#Elm1 {
  background-color: #300;
}

#Elm2 {
  background-color: #6B0;
}

#Elm3 {
  background-color: #90A;
}

#Elm4 {
  background-color: #B00;
}

div {
  z-index: -1;
}

#div1 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 25%;
}

#div2 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 50%;
}

#div3 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 75%;
}
<div class="header"> <span style="width: 100px;display: block;float: left;margin-right: 20px;">vertical align</span> <span>font-size(em)</span> </div>
<div>

  <select name="sl1" id="sl1">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip1" />
  <br>
  <select name="sl2" id="sl2">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip2" />
  <br>
  <select name="sl3" id="sl3">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip3" />
  <br>
  <select name="sl4" id="sl4">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip4" />
  <br>
  <button id="btnRandom" (onclick)="random()">Random</button>
</div>
<div id="elms">
  <span id="Elm1">one</span>
  <span id="Elm2">two</span>
  <span id="Elm3">three</span>
  <span id="Elm4">four</span>
  <div id="div1"></div>
  <div id="div2"></div>
  <div id="div3"></div>
</div>
<div id="viewer"></div>

Cet extrait est créé par Duannx .


Source: Veuillez noter qu'il s'agit d'un extrait de Vertical-Align: All You Need To Know écrit par Christopher Aue.

35
Paolo Forgia

La question est de savoir pourquoi vertical-align: baseline; ignoré. Eh bien, je ne pense pas. Dans votre premier extrait, vous utilisez baseline et bottom ce qui donne clairement une différence entre les deux <span> éléments. Alors, que fait baseline? Eh bien baseline Aligne la ligne de base de l'élément avec la ligne de base de l'élément parent. Dans l'exemple ci-dessous, j'ai copié et ajusté certaines parties pour donner la différence.

span.one {vertical-align:baseline}
span.two {vertical-align:middle;}
<p>
  <span class="one">one</span> <span class="two">two</span>
</p>

Comme vous pouvez le voir, l'alignement baseline agit normalement tout comme l'alignement middle.

Permet maintenant de tester autre chose. permet d'échanger l'alignement de baseline et middle et d'éditer middle et d'ajouter un troisième <span>

span.one { vertical-align: top;}
span.two { vertical-align: baseline;}

span.three {vertical-align: middle; height: 20px; }
p {
height: 50px;
background-color: grey;
}
<p>
  <span class="one">one</span> <span class="two">two</span> <span class="two">two</span><br><br> <span class="three">three</span>
</p>

Maintenant, si vous éditez le deuxième extrait et jetez un œil au vertical-align de <span class="three"> vous pouvez voir clairement qu'en changeant l'alignement le texte change sa position.

Mais votre question concerne le texte sur la même ligne, jetons un coup d'œil à l'extrait ci-dessous.

span.one { vertical-align: middle;}
span.two { vertical-align: baseline;}

span.three {vertical-align: middle; height: 20px; }
p {
height: 50px;
background-color: grey;
}
<p>
  <span class="one">one</span> <span class="two">two</span> <span class="two">two</span><span class="three">three</span>
</p>

Comme vous pouvez le voir dans ce troisième extrait, j'ai placé le troisième <span> à côté d'un et deux. Et cela fait une différence. Le baseline dans ce cas est différent de l'alignement middle. En effet, le baseline saisit le baseline du parent. comme la hauteur du parent est normale, cela n'affecte pas l'alignement de baseline et top. mais quand vous utiliserez middle ou sub c'est clairement une différence.

Pour plus d'informations sur chaque alignement, consultez ceci lien .

5
Deathstorm