Jak ustawić margines lub wypełnienie jako procent wysokości pojemnika nadrzędnego?


236

Miałem mózg nad tworzeniem pionowego wyrównania w css, używając następującego

.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>

Chociaż zdawało się, że to działa w tym przypadku, byłem zaskoczony, że kiedy zwiększyłem lub zmniejszyłem szerokość mojego podstawowego div, pionowe wyrównanie zaskoczy. Spodziewałem się, że kiedy ustawię właściwość padding-top, potrwa to wypełnienie jako procent wysokości pojemnika nadrzędnego, który w naszym przypadku jest podstawą, ale powyższa wartość 50 procent jest obliczana jako procent szerokość. :(

Czy istnieje sposób na ustawienie marginesu i / lub marginesu jako procent wysokości bez konieczności korzystania z JavaScript?

Odpowiedzi:


223

Rozwiązaniem jest to, że tak, pionowe i wyściółka margines są względem szerokości, ale topi bottom nie są.

Więc po prostu umieść div w innym, a w div div, użyj czegoś w stylu top:50%(pamiętaj position, że to nie działa)


3
topdziała świetnie do zmiany rozmiaru na podstawie wysokości przeglądarki / okna. Co powiesz na posiadanie div pod tym div? Jak możesz clear2. dywizji być pod dywanem, który jest przesunięty w dół o top:50%??
Federico

Naucz się czegoś nowego. Nie wiedziałem wcześniej, że pionowe wypełnienie i margines są względem szerokości. Dziękuję Ci.
shaosh,

5
Możliwe jest również dodanie div „spacer” z ustawioną wysokością procentową. Wydaje się trochę brudny, ale działa. zobacz tę odpowiedź .
WCByrne

4
Co wieczne @%! ^? Dlaczego pionowy margines i wypełnienie odnoszą się do szerokości ? CO? Dlaczego, u licha, podjęto tę decyzję?
tymczasowego

Twoja odpowiedź jest wyjątkowo nieproporcjonalnie wyższa w porównaniu do poniższej odpowiedzi Alaina, która daje ogólne rozwiązanie, a ja uznałem ją za bardzo pomocną i prawie jej nie widziałem. top: 50%nie jest bardzo przydatne, jeśli chcesz wyrównać zawartość według własnego centrum.
okovko

35

Odpowiedź na nieco innym pytaniem: Można użyć vhjednostki do elementów pad do środka wziernika :

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

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

Dlaczego ta odpowiedź nie jest głosowana wyżej? Czy jest coś nie tak z używaniem vh?
AlanH,

3
Ponieważ nie jest to odpowiedź dopasowana do pierwotnego pytania, jest to przydatna sztuczka, która działa tylko w kilku powiązanych przypadkach.
willoller,

używanie vhjest prawie takie samo jak procenty ... w niektórych przypadkach nawet gorsze. Ta odpowiedź nie ma znaczenia dla pytania
vsync

33

Oto dwie opcje naśladowania potrzebnego zachowania. Nie jest to ogólne rozwiązanie, ale może pomóc w niektórych przypadkach. Odstępy pionowe są tutaj obliczane na podstawie rozmiaru elementu zewnętrznego, a nie jego elementu nadrzędnego, ale sam ten rozmiar może być względny względem elementu nadrzędnego, w ten sposób odstępy również będą względne.

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

Pierwsza opcja: użyj pseudoelementów, tutaj odstępy pionowe i poziome odnoszą się do zewnętrznego. Próbny

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

Przesunięcie poziomego odstępu do elementu zewnętrznego powoduje, że jest on względem rodzica elementu zewnętrznego. Próbny

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

Druga opcja: użyj bezwzględnego pozycjonowania. Próbny

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

10

Aby element potomny był pozycjonowany absolutnie na podstawie elementu macierzystego, musisz ustawić pozycję względną na elemencie macierzystym ORAZ pozycję bezwzględną na elemencie potomnym.

Następnie na elemencie potomnym „góra” odnosi się do wysokości elementu nadrzędnego. Musisz więc „przetłumaczyć” dziecku 50% jego własnego wzrostu.

.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>

Istnieje inne rozwiązanie wykorzystujące Flex Box.

.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>

Znajdziesz zalety / wady dla obu.


1
Używanie translacji jest jedynym rzeczywistym sposobem przesuwania elementu w pionie w stosunku do jego własnego rozmiaru.
Eran Goldin,

Dzięki za to. To powinna być wybrana odpowiedź.
Wessam El Mahdy

6

Można to osiągnąć za pomocą writing-modenieruchomości. Jeśli ustawisz element na writing-modetryb zapisu pionowego, taki jak vertical-lrprocentowe wartości jego potomków dla wypełnienia i marginesu, w obu wymiarach, staną się względne względem wysokości zamiast szerokości.

Ze specyfikacji :

. . . procenty na marginesie i właściwości wypełnienia, które są zawsze obliczane w odniesieniu do szerokości bloku zawierającego w CSS2.1, są obliczane w odniesieniu do rozmiaru wstawianego bloku zawierającego w CSS3.

Definicja rozmiaru wbudowanego :

Pomiar w wymiarze inline: odnosi się do fizycznej szerokości (wymiar poziomy) w trybach zapisu poziomego i do wysokości fizycznej (wymiar pionowy) w trybach zapisu pionowego.

Przykład z elementem o zmiennym rozmiarze, w którym poziome marginesy odnoszą się do szerokości, a pionowe marginesy odnoszą się do wysokości.

.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>

Korzystanie z trybu zapisu pionowego może być szczególnie przydatne w sytuacjach, w których chcesz, aby proporcje elementu pozostały stałe, ale chcesz, aby jego rozmiar był skalowany w zależności od jego wysokości zamiast szerokości.


To jest, IMO, bardziej eleganckie rozwiązanie, ale (od 2018-05-05) tryby pisania pionowego nie są dobrze obsługiwane . Mam nadzieję, że wkrótce się to zmieni.
zanerock

1
@zanerock Jestem całkiem pewien, że tabela kompatybilności MDN jest nieaktualna. Mówi na przykład, że Safari potrzebuje -webkit-prefiksu, ale zgodnie z caniuse nie wymagał prefiksu od Safari 11. Czy wypróbowałeś go w przeglądarce, w której nie działał?
James T

1
Nie, muszę przyznać, że po prostu założyłem, że było dobre, nawet zautomatyzowane.
zanerock

4

Innym sposobem wyśrodkowania tekstu w jednej linii jest:

.parent{
  position: relative;
}

.child{
   position: absolute;
   top: 50%;
   line-height: 0;
}

Lub tylko

.parent{
  overflow: hidden; /* if this ins't here the parent will adopt the 50% margin of the child */
}

.child{
   margin-top: 50%;
   line-height: 0;
}

0

Wypełnienie w 50% nie wyśrodkuje twojego dziecka, umieści je poniżej środka. Myślę, że naprawdę chcesz mieć wyściółkę z 25%. Może po prostu kończy Ci się miejsce, gdy Twoje treści stają się wyższe? Czy próbowałeś również ustawić margines górny zamiast padding-top?

EDYCJA: Nevermind, mówi strona w3schools

% Określa dopełnienie w procentach szerokości elementu zawierającego

Więc może zawsze używa szerokości? Nigdy nie zauważyłem.

To, co robisz, można osiągnąć za pomocą display: table (przynajmniej dla nowoczesnych przeglądarek). Technika jest wyjaśniona tutaj .


1
Dzięki Spliff. Rozumiem, że moje 50% nie wyśrodkuje treści div. Mam tylko jedną linię tekstu, która musi być wyśrodkowana pionowo. Bardzo dziękuję za link!
Ryan

3
Jeśli jest to tylko jeden wiersz tekstu, czy rozważałeś użycie absurdalnie dużego line-height, tzn. Czy wysokość linii to 200 pikseli?
SpliFF

@ Ryan, aby wyśrodkować tekst w pionie, patrz stackoverflow.com/questions/8865458/...
użytkownik

twój link jest zepsuty
cichy

0

To bardzo interesujący błąd. (Moim zdaniem i tak jest to błąd) Niezłe znalezisko!

Jeśli chodzi o to, jak to ustawić, poleciłbym odpowiedź Camilo Martina. Ale dlaczego? Chciałbym to trochę wyjaśnić, jeśli nie macie nic przeciwko.


W specyfikacjach CSS znalazłem:

„padding”
Procenty: odnoszą się do szerokości bloku zawierającego

… Co jest dziwne, ale w porządku.

Tak więc z rodzicem width: 210pxi dzieckiem padding-top: 50%otrzymuję obliczoną / obliczoną wartość padding-top: 96.5px- która nie jest oczekiwana 105px.

Jest tak, ponieważ w systemie Windows (nie jestem pewien co do innych systemów operacyjnych) rozmiar wspólnych pasków przewijania jest domyślnie 17px × 100%(lub w 100% × 17pxprzypadku poziomych pasków). Ci 17pxsą odjąć przed obliczenia 50%, stąd 50% of 193px = 96.5px.


Jest powód, dla którego podano
manikanta
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.