293 votes

Comment définir la marge ou le rembourrage en pourcentage de la hauteur du conteneur parent ?

Je me suis creusé la tête pour créer un alignement vertical en css à l'aide des éléments suivants

.base{
        background-color:green;
        width:200px;
        height:200px;
        overflow:auto;
        position:relative;
    }

    .vert-align{
        padding-top:50%;
        height:50%;
    }

<!-- and used the following div structure. -->

    <div class="base">
       <div class="vert-align">
           Content Here
       </div>
    </div>

Bien que cela semble fonctionner dans ce cas, j'ai été surpris de constater que lorsque j'augmentais ou diminuais la largeur de ma division de base, l'alignement vertical se brisait. Je m'attendais à ce que, lorsque je définissais la propriété padding-top, le padding soit calculé en pourcentage de la hauteur du conteneur parent, qui est la base dans notre cas, mais la valeur ci-dessus de 50 % est calculée en pourcentage de la largeur.

Existe-t-il un moyen de définir le rembourrage et/ou la marge en tant que pourcentage de la hauteur, sans recourir à JavaScript ?

256voto

Camilo Martin Points 5586

Le problème est que oui, le rembourrage vertical et la marge sont relatifs à la largeur, mais que top et bottom ne le sont pas.

Il suffit donc de placer une div à l'intérieur d'une autre, et dans la div intérieure, d'utiliser quelque chose comme top:50% (souvenez-vous position importe si cela ne fonctionne toujours pas)

3 votes

top fonctionne très bien pour le redimensionnement en fonction de la hauteur du navigateur/de la fenêtre. Que diriez-vous d'avoir une div sous cette div ? Comment pouvez-vous clear la 2e division pour être sous la division qui est décalée vers le bas d'un top:50% ? ?

0 votes

Apprendre quelque chose de nouveau. Je ne savais pas auparavant que le padding vertical et la marge étaient relatifs à la largeur. Merci.

9 votes

Il est également possible d'ajouter une division "espaceur" dont la hauteur est définie en pourcentage. Cela semble un peu sale mais cela fonctionne. cette réponse .

54voto

willoller Points 3404

Une réponse à une question légèrement différente : Vous pouvez utiliser vh pour placer les éléments au centre de la fenêtre d'observation :

.centerme {
    margin-top: 50vh;
    background: red;
}

<div class="centerme">middle</div>

1 votes

Pourquoi cette réponse n'est-elle pas votée plus haut ? Y a-t-il quelque chose de mal à utiliser vh ?

18 votes

C'est parce qu'il ne s'agit pas d'une réponse adaptée à la question initiale, mais d'une astuce utile qui ne fonctionne que dans quelques cas connexes.

2 votes

En utilisant vh est presque identique aux pourcentages... voire pire dans certains cas. Cette réponse n'est pas pertinente pour la question

36voto

user Points 1438

Voici deux options pour émuler le comportement nécessaire. Ce n'est pas une solution générale, mais elle peut être utile dans certains cas. L'espacement vertical est ici calculé sur la base de la taille de l'élément extérieur, et non de son parent, mais cette taille peut elle-même être relative au parent et, de cette façon, l'espacement sera également relatif.

<div id="outer">
    <div id="inner">
        content
    </div>
</div>

Première option : utiliser des pseudo-éléments, ici les espacements verticaux et horizontaux sont relatifs à l'extérieur. Démo

#outer::before, #outer::after {
    display: block;
    content: "";
    height: 10%;
}
#inner {
    height: 80%;
    margin-left: 10%;
    margin-right: 10%;
}

Le fait de déplacer l'espacement horizontal vers l'élément extérieur le rend relatif au parent de l'élément extérieur. Démo

#outer {
    padding-left: 10%;
    padding-right: 10%;
}

Deuxième option : utiliser le positionnement absolu. Démo

#outer {
    position: relative;
}
#inner {
    position: absolute;
    left: 10%;
    right: 10%;
    top: 10%;
    bottom: 10%;
}

13voto

alain Points 629

Pour que l'élément enfant soit positionné de manière absolue par rapport à son élément parent, vous devez définir une position relative sur l'élément parent ET une position absolue sur l'élément enfant.

Ensuite, sur l'élément enfant, "top" est relatif à la hauteur du parent. Vous devez donc également "translater" vers le haut l'élément enfant à 50 % de sa propre hauteur.

.base{
    background-color: green;
    width: 200px;
    height: 200px;
    overflow: auto;
    position: relative;
}

.vert-align {
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
}

    <div class="base">
        <div class="vert-align">
            Content Here
        </div>
    </div>

Il existe une autre solution qui consiste à utiliser une boîte flexible.

.base{
    background-color:green;
    width: 200px;
    height: 200px;
    overflow: auto;
    display: flex;
    align-items: center;
}

<div class="base">
    <div class="vert-align">
        Content Here
    </div>
</div>

Vous trouverez des avantages/désavantages pour les deux.

2 votes

L'utilisation de translate est le seul véritable moyen de déplacer verticalement un élément par rapport à sa propre taille.

0 votes

Merci pour cela. Ce devrait être la réponse choisie.

11voto

James T Points 578

Cela peut être réalisé avec le writing-mode propriété. Si vous définissez la propriété writing-mode à un mode d'écriture vertical, tel que vertical-lr Dans le cas d'un produit de ce type, les pourcentages de remplissage et de marge de ses descendants, dans les deux dimensions, deviennent relatifs à la hauteur et non à la largeur.

De la spec :

. les pourcentages des propriétés margin et padding, qui sont toujours calculés par rapport à la largeur du bloc contenant en CSS2.1, sont calculés par rapport à la largeur du bloc de référence. taille en ligne du bloc contenant en CSS3.

La définition de taille en ligne :

Une mesure dans la dimension en ligne : fait référence à la largeur physique (dimension horizontale) dans les modes d'écriture horizontaux, et à la hauteur physique (dimension verticale) dans les modes d'écriture verticaux.

Exemple, avec un élément redimensionnable, où les marges horizontales sont relatives à la largeur et les marges verticales sont relatives à la hauteur.

.resize {
  width: 400px;
  height: 200px;
  resize: both;
  overflow: hidden;
}

.outer {
  height: 100%;
  background-color: red;
}

.middle {
  writing-mode: vertical-lr;
  margin: 0 10%;
  width: 80%;
  height: 100%;
  background-color: yellow;
}

.inner {
  writing-mode: horizontal-tb;
  margin: 10% 0;
  width: 100%;
  height: 80%;
  background-color: blue;
}

<div class="resize">
  <div class="outer">
    <div class="middle">
      <div class="inner"></div>
    </div>
  </div>
</div>

L'utilisation d'un mode d'écriture vertical peut être particulièrement utile dans les cas où vous souhaitez que le rapport hauteur/largeur d'un élément reste constant, mais que sa taille soit mise à l'échelle en fonction de sa hauteur plutôt que de sa largeur.

0 votes

C'est, IMO, serait la solution la plus élégante, mais (à partir de 2018-05-05), les modes d'écriture verticaux ne sont pas bien supportés . Espérons que cela change bientôt.

1 votes

@zanerock Je suis presque certain que le tableau de compatibilité MDN est dépassé. Par exemple, il est dit que Safari a besoin de l'option -webkit- mais selon caniuse le préfixe n'est plus nécessaire depuis Safari 11. Avez-vous essayé avec un autre navigateur dans lequel il n'a pas fonctionné ?

1 votes

Non, je dois admettre que j'ai juste supposé que c'était bon, automatisé même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X