Wyśrodkuj DIV nierównomiernie za pomocą CSS

23

Centruję DIV wewnątrz innego DIV za pomocą Flexboksa. Pomyśl o oknie dialogowym, które pojawia się na środku ekranu w razie potrzeby.

Działa dobrze, jednak wyglądałoby to znacznie lepiej, gdyby przestrzeń powyżej i poniżej okna dialogowego nie była dokładnie równa, mając 40% pozostałej przestrzeni powyżej i 60% poniżej okna dialogowego. Jest to trudne, ponieważ wysokość okna dialogowego zmienia się w zależności od ilości tekstu w środku.

Na przykład, jeśli wysokość przeglądarki wynosi 1000 pikseli, a wysokość okna dialogowego wynosi 400 pikseli, chcę, aby pozostała przestrzeń pionowa (600 pikseli) znajdowała się 240 pikseli powyżej i 360 pikseli poniżej okna dialogowego. Mógłbym to zrobić za pomocą Javascript, ale jestem ciekawy, czy istnieje jakiś sprytny sposób z CSS. Próbowałem dodać dolny margines do #dialogBox DIV, ale to nie działa, gdy wysokość okna dialogowego zbliża się do wysokości przeglądarki.

#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
źródło
Czy potrzebujesz zewnętrznego panelu, aby pokryć całą rzutnię? Jeśli nie, wybrałbym rozwiązanie z css-tricks.com/centering-css-complete-guide , sekcja „Zarówno poziomo, jak i pionowo / Czy element ma nieznaną szerokość i wysokość?” I zmodyfikowałem wartości procentowe translacji. (I nawet jeśli potrzebujesz nadrzędnego pełnego obszaru ekranu [tło?], Powinieneś być w stanie połączyć oba - zrezygnować z elastyczności, reszta pozostaje.)
04FS
Tak, mam efekt ściemniania na panelu zewnętrznym, więc musi on obejmować całą rzutnię. Ale mógłbym dodać jeszcze jeden DIV, a twoje rozwiązanie działałoby dobrze. Dzięki 04FS!
Björn Morén
Ze względu na dokładność mówisz o wyrównaniu w pionie, a nie o centrowaniu.
Michael Benjamin

Odpowiedzi:

11

Użyj pseudoelementu i kierunku kolumny, aby zasymulować białą przestrzeń. Po prostu dostosuj flex-growpseudoelement, aby kontrolować, ile wolnego miejsca każdy powinien zająć. Równy flex-grow zapewni równe miejsce:

Możesz także użyć 2i 3. Po prostu musimy zachować ten sam stosunek:

Innym pomysłem jest użycie najwyższej wartości równej 40%i skorygowanie pozycji za pomocą translacji (ta sama logika jak 50%przy centrowaniu)

#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
źródło
Wielkie dzięki Temani! Oba rozwiązania działają idealnie i wydają się identyczne, z wyjątkiem specjalnego przypadku, w którym okno dialogowe jest wyższe niż przeglądarka. Pierwsze rozwiązanie utrzymuje wyrównanie górnej części okna dialogowego z górną częścią przeglądarki, przycinanie u dołu. Drugie uprawy zarówno na dole, jak i na górze. To tylko kwestia preferencji.
Björn Morén
5

To rozwiązanie wykorzystuje display: grid, jest to nowa funkcja, więc sprawdź obsługę przeglądarki i kliknij tutaj, aby dowiedzieć się więcej.

Oto linia kontrolująca górne i dolne spacje:

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

Treść fragmentu tekstu można edytować, aby sprawdzić, czy pole pozostaje wyśrodkowane, nawet jeśli zmienia się wysokość.

#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
źródło
1
Rozważałbym użycie 4fr auto 6fr. To, co masz, działa, ale z pewnym przepełnieniem, ponieważ 40% + 60% + 1fr zawsze będzie większe niż 100% i jesteś centrowany, więc przepełnienie zostanie podzielone równo od góry i dołu: jsfiddle.net/cobutn0e/2 . Zauważysz również, że nie jest to w 100% oczekiwane
Temani Afif
Właśnie zmieniłem 1fr na auto, wolę pozostawić go jako%, aby dopasować wartości pytania. Wielkie dzięki za wskazanie błędu!
rafaelcastrocouto
auto i 1fr dadzą taki sam wynik w twoim przypadku, problemem jest użycie procentu; 1fr=minmax(auto,1fr)i w twoim przypadku spadnie, autoponieważ nie ma wolnego miejsca, ponieważ 40% + 60% = 100% (dlatego zawsze będziesz miał przepełnienie)
Temani Afif
1
oto kolejne skrzypce ilustrujące mój punkt widzenia: jsfiddle.net/cobutn0e/3 zauważ, jak 3 pierwsze są takie same, trzecie spada do 0, a ostatnie jest tym, co zasugerowałem
Temani Afif
Teraz rozumiem, ma to sens. Użyję 40fr i 60fr, ponieważ pod koniec dnia jest tak samo. Jeszcze raz dziękuję za poświęcony czas na naukę mnie!
rafaelcastrocouto
4

Możesz dodać dzielniki div i ustawić Flex-Grow ze współczynnikiem 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
źródło
Dopiero teraz zobaczyłem odpowiedź @Temani Afif, ale działa to tak samo z „po” i „przed”
Itay Gal
0

Prosty sposób przy użyciu pozycji i marginesu, przyjąłem, że wysokość okna dialogowego wynosi zawsze 40% wysokości przeglądarki.

.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
źródło
Cześć, witamy, następnym razem proszę uważnie przeczytać pytanie: „wysokość okna dialogowego zależy od ilości tekstu w środku”.
rafaelcastrocouto
1
@rafaelcastrocouto - teraz kontroluje go za pomocą maksymalnej wysokości w procentach, ponieważ pozostawienie go bez wysokości nie rozwiąże pytania dotyczącego estetyki górnej i dolnej przestrzeni.
Anshul Chaurasia