Centrer un DIV de manière inégale en utilisant CSS

23

Je centre un DIV à l'intérieur d'un autre DIV à l'aide d'un flexbox. Pensez à une fenêtre de dialogue qui apparaît au centre de l'écran en cas de besoin.

Cela fonctionne bien, mais il serait beaucoup mieux si l'espace au-dessus et en dessous de la boîte de dialogue n'était pas exactement égal, avec 40% de l'espace restant au-dessus et 60% en dessous de la boîte de dialogue. Cela devient difficile car la hauteur de la boîte de dialogue varie avec la quantité de texte à l'intérieur.

Ainsi, par exemple, si la hauteur du navigateur est de 1000 px et la hauteur de la fenêtre de dialogue est de 400 px, je veux que l'espace vertical restant (600 px) soit 240 px au-dessus et 360 px en dessous de la boîte de dialogue. Je pourrais le faire avec Javascript, mais je suis curieux de savoir s'il existe un moyen intelligent avec CSS. J'ai essayé d'ajouter une marge inférieure à la DIV #dialogBox, mais cela ne fonctionne pas lorsque la hauteur de la boîte de dialogue approche de la hauteur du navigateur.

#dialogBoxPanel
  {
  position:absolute;
  display:flex;
  align-items:center;
  justify-content:center;
  left:0px;
  top:0px;
  width:100%;
  height:100%;
}
#dialogBox
  {
  width:350px;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Text</div>
</div>

Björn Morén
la source
Avez-vous besoin du panneau extérieur pour couvrir toute la fenêtre? Sinon, j'irais avec la solution de css-tricks.com/centering-css-complete-guide , section "À la fois horizontalement et verticalement / L'élément est-il de largeur et de hauteur inconnues?", Et modifierais les valeurs de pourcentage de traduction. (Et même si vous avez besoin de la taille de la fenêtre d'affichage complète des parents [toile de fond?], Vous devriez être en mesure de combiner les deux - supprimez les éléments flexibles, les séjours de repos.)
04FS
Oui, j'ai un effet de gradation sur le panneau extérieur, il doit donc couvrir toute la fenêtre. Mais je pourrais ajouter un autre DIV à l'intérieur, et votre solution fonctionnerait bien. Merci 04FS!
Björn Morén
Par souci de précision, vous parlez d'alignement vertical, pas de centrage.
Michael Benjamin

Réponses:

11

Utilisez le pseudo-élément et la direction de la colonne pour simuler l'espace blanc. Ajustez simplement flex-growle pseudo-élément pour contrôler la quantité d'espace libre que chacun devrait prendre. Une flex-grow égale donnera un espace égal:

Vous pouvez également utiliser 2et 3. Nous devons simplement garder le même ratio:

Une autre idée est d'utiliser une valeur supérieure égale à 40%et de rectifier la position avec translate (même logique que 50%lors du centrage)

#dialogBoxPanel {
  position: absolute;;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  /* the center */
  background:linear-gradient(red,red) center/100% 1px no-repeat;
}

#dialogBox {
  position:relative;
  top:40%;
  width: 350px;
  transform:translateY(-40%);
  margin:auto;
  border:1px solid;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>

Temani Afif
la source
Merci beaucoup Temani! Les deux solutions fonctionnent parfaitement et semblent identiques, sauf dans le cas particulier où la boîte de dialogue est plus haute que le navigateur. La première solution maintient le haut de la boîte de dialogue aligné avec le haut du navigateur, recadrant en bas. La seconde récolte à la fois en bas et en haut. Juste une question de préférence.
Björn Morén
5

Cette solution utilise display: grid, c'est une nouvelle fonctionnalité alors assurez-vous de vérifier la prise en charge du navigateur et cliquez ici pour en savoir plus.

C'est la ligne qui contrôle les espaces supérieurs et inférieurs:

grid-template-rows: 40fr [content-start] auto [content-end] 60fr;

Le contenu du texte d'extrait peut être modifié pour que vous puissiez vérifier que la case reste centrée même si la hauteur change.

#dialogBoxPanel {
    display: grid;
    place-content: center;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    grid-template-rows: 40fr [content-start] auto [content-end] 60fr;
}
#dialogBox {
    border: 1px solid;
    width: 350px;
    grid-area: content;
}
<div id="dialogBoxPanel">
   <div id="dialogBox" contenteditable>Text</div>
</div>

rafaelcastrocouto
la source
1
J'envisagerais l'utilisation de 4fr auto 6fr. Ce que vous avez fonctionne mais avec un débordement puisque 40% + 60% + 1fr sera toujours plus grand que 100% et vous vous centrez donc le débordement sera divisé également en haut et en bas: jsfiddle.net/cobutn0e/2 . Vous remarquerez également que ce n'est pas à 100% comme prévu
Temani Afif
Je viens de changer le 1fr en auto, je préfère le laisser en% pour correspondre aux valeurs de la question. Merci beaucoup d'avoir signalé l'erreur!
rafaelcastrocouto
auto et 1fr donneront le même résultat dans votre cas, le problème est l'utilisation du pourcentage; 1fr=minmax(auto,1fr)et dans votre cas, il tombera autocar il n'y a pas d'espace libre car 40% + 60% = 100% (c'est pourquoi vous aurez toujours un débordement)
Temani Afif
1
voici un autre violon pour illustrer mon propos: jsfiddle.net/cobutn0e/3 remarquez comment les 3 premiers sont les mêmes, le troisième tombe à 0 et le dernier est ce que j'ai suggéré
Temani Afif
Maintenant je comprends, c'est logique. Je vais utiliser 40fr et 60fr car c'est la même chose à la fin de la journée. Merci encore d'avoir pris le temps de m'apprendre!
rafaelcastrocouto
4

Vous pouvez ajouter des diviseurs d'espacement et définir la flex-croissance avec un rapport 4: 6.

#dialogBoxPanel {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;

  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
}

#dialogBox {
  width: 350px;
  border: 1px solid black;
}

.spacer-top{
  flex-grow: 4;
}
.spacer-bottom{
  flex-grow: 6;
<div id="dialogBoxPanel">
  <div class="spacer-top"></div>
  <div id="dialogBox">Text</div>
  <div class="spacer-bottom"></div>
</div>

Itay Gal
la source
Seulement maintenant vu la réponse de @Temani Afif, mais cela fonctionne de la même manière avec "après" et "avant"
Itay Gal
0

De manière simple en utilisant la position et la marge, j'ai supposé que la hauteur de votre dialogue est toujours de 40% de la hauteur du navigateur.

.modal{
            max-height:50%;
            width:400px;
            margin: 10% auto 5% auto;
            position:absolute;
            top:0;
            bottom:0;
            right:0;
            left:0;
            overflow-y: auto
        }
        .modal-body{
            background-color: beige;
            padding: 20px;
            line-height: 21px
        }

HTML

<div class="modal">
 <div class="modal-body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea </div>
</div>
Anshul Chaurasia
la source
Bonjour, la prochaine fois, veuillez lire attentivement la question, elle indique: "la hauteur de la boîte de dialogue varie en fonction de la quantité de texte à l'intérieur."
rafaelcastrocouto
1
@rafaelcastrocouto - maintenant le contrôler via la hauteur maximale en pourcentage, car le laisser sans hauteur ne résoudra pas le problème de l'esthétique de l'espace supérieur et inférieur.
Anshul Chaurasia