CSS 100% wysokości z wypełnieniem / marginesem

813

W przypadku HTML / CSS, w jaki sposób mogę utworzyć element, który ma szerokość i / lub wysokość stanowiącą 100% jego elementu nadrzędnego i nadal ma odpowiednie dopełnienie lub marginesy?

Przez „właściwy” rozumiem, że jeśli mój element nadrzędny jest 200pxwysoki i określam za height = 100%pomocą padding = 5px, spodziewam się, że powinienem uzyskać 190pxwysoki element ze border = 5pxwszystkich stron, ładnie wyśrodkowany w elemencie nadrzędnym.

Teraz wiem, że nie tak określa się standardowy model pudełkowy, że powinien on działać (chociaż chciałbym wiedzieć, dlaczego dokładnie ...), więc oczywista odpowiedź nie działa:

#myDiv {
    width: 100%
    height: 100%;
    padding: 5px;
}

Wydaje mi się jednak, że musi istnieć NIEZWYKŁY sposób niezawodnego wywołania tego efektu dla rodzica o dowolnej wielkości. Czy ktoś zna sposób na wykonanie tego (pozornie prostego) zadania?

Aha, a dla przypomnienia, nie jestem szczególnie zainteresowany kompatybilnością z IE, więc powinno to (miejmy nadzieję) nieco ułatwić.

EDYCJA: Ponieważ poproszono o przykład, oto najprostszy, jaki mogę wymyślić:

<html style="height: 100%">
    <body style="height: 100%">
        <div style="background-color: black; height: 100%; padding: 25px"></div>
    </body>
</html>

Wyzwanie polega na tym, aby czarna ramka pojawiła się z wypełnieniem 25 pikseli na wszystkich krawędziach, bez powiększania strony do rozmiarów pasków przewijania.

Toji
źródło
Znalazłem te dwa rozwiązania, które są najbardziej niezawodne: http://www.xs4all.nl/~peterned/examples/csslayout1.html http://themaninblue.com/experiment/footerStickAlt/ Czy masz jakiś konkretny kod HTML, który możemy zobaczyć i bawić się?
Nick Presta

Odpowiedzi:

755

Nauczyłem się robić takie rzeczy, czytając „ PRO HTML i CSS Design Patterns ”. Jest display:blockto domyślna wartość wyświetlana dla div, ale ja chcę ją wyrazić. Pojemnik musi być odpowiedniego typu; positionatrybut jest fixed, relativealbo absolute.

.stretchedToMargin {
  display: block;
  position:absolute;
  height:auto;
  bottom:0;
  top:0;
  left:0;
  right:0;
  margin-top:20px;
  margin-bottom:20px;
  margin-right:80px;
  margin-left:80px;
  background-color: green;
}
<div class="stretchedToMargin">
  Hello, world
</div>

Fiddle przez komentarz Nooshu

Frank Schwieterman
źródło
42
Znakomite rozwiązanie, będzie zakładką do tego. Po prostu szybko dodałem go do jsfiddle.net/Rpdr9 dla każdego, kto chce demo na żywo. Mam nadzieję, że nie masz nic przeciwko.
Nooshu,
16
Chociaż @Toji nie dbało o kompatybilność z IE, niestety muszę. To rozwiązanie początkowo nie działało pod IE6. Dodanie IE9.js Dean Edwards do strony spowodowało, że to zadziałało. Teraz muszę tylko mieć nadzieję i modlić się, aby pozycjonowanie względne / absolutne nie wkręcało się w coś w elemencie dziecięcym ...
Christopher Parker
24
-1 (choć wygląda na to, że jestem tutaj mniejszością: P). Zakłada się, że pole może być absolutnie ustawione; ludzie już nadużywają pos: abs tak jak jest, nie potrzebują tej amunicji. Weźmy ten przykład: „panele” div z wieloma tablicami „div” klasy. „panele” mają {przepełnienie: ukryte; height: 300px;}, a „panel” mają różną zawartość / wysokość-treść, z {border: # 000 solid 1px; float: left; margines z prawej: 10 pikseli;}. Ustaw wszystkie „panele” na wysokość „paneli” bez utraty granic w dowolnym punkcie. Dywizje „panelowe” nie mogą być tutaj: abs'd tutaj. Rozwiązanie @ Marco działa jednak w tym scenariuszu.
eternicode
8
Och wow, rozumiem. top:0, bottom:0Zasadniczo „rozciągania” na zewnątrz tego elementu. Mogę tylko go do pracy z position:absolutechociaż
Matt
7
Czy nie możesz po prostu zrobić top:20px;bottom:20px;left:20px;right:20px;zamiast marży?
chowey 13.03.13
391

W CSS3 pojawiła się nowa właściwość , której można użyć do zmiany sposobu obliczania szerokości / wysokości przez model pola, nazywany jest on wielkością pudełka.

Ustawienie tej właściwości na wartość „obramowanie” powoduje, że dowolny element, który zastosujesz, nie będzie rozciągał się po dodaniu dopełnienia lub ramki. Jeśli zdefiniujesz coś o szerokości 100 pikseli i dopełnieniu 10 pikseli, nadal będzie mieć szerokość 100 pikseli.

box-sizing: border-box;

Zobacz tutaj, aby uzyskać wsparcie przeglądarki . Nie działa dla IE7 i niższych, jednak uważam, że IE7.js Deana Edwarda dodaje obsługę. Cieszyć się :)

Marco Jardim
źródło
45
Wreszcie! Na tę dokładną funkcję czekam już od około 10 lat. Szkoda IE7 nie obsługuje tego, ale zawsze myślę, że ludzie, którzy nadal używają IE, nie zasługują na piękny układ.
cronoklee
2
Działa to na domyślnej przeglądarce iPhone / Safari i Androida, podczas gdy powyższe rozwiązanie absolutnie nie działało.
Spud
18
Jest to w zasadzie to samo, co model pudełkowy trybu dziwactw IE . Zabawne jest to, że wszyscy nienawidzą w IE, ale teraz border-boxjest bohaterem każdego :)
Matt Greer,
14
Do Twojej wiadomości, prefiks przeglądarki do zmiany rozmiaru pudełka jest teraz odrzucany dla wszystkich oprócz -moz. Zobacz paulirish.com/2012/box-sizing-border-box-ftw i komentarze do dobrej dyskusji
aponzani
3
Tak! To właściwa odpowiedź! Wysokość 100% teraz skaluje rzeczy poprawnie względem swoich rodziców, bez rozlewania się. Dałbym milion + 1, gdybym mógł.
Andrew Mao,
65

Rozwiązaniem jest wcale NIE używać wysokości i szerokości! Przymocuj wewnętrzne pudełko za pomocą górnego, lewego, prawego, dolnego, a następnie dodaj margines.

.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
  <div class="box" style="background:green">
    <div class="box" style="background:lightblue">
      This will show three nested boxes. Try resizing browser to see they remain nested properly.
    </div>
  </div>
</div>

żółtko
źródło
6
Podnieś głos, ponieważ technicznie masz rację, ale jest to w zasadzie ta sama odpowiedź, co odpowiedź Franka (co, moim zdaniem, jest nieco bardziej przyjazne dla niechlujnych przeglądarek.)
Toji
39

Lepszym sposobem jest właściwość calc (). Twoja sprawa wyglądałaby następująco:

#myDiv {
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    padding: 5px;
}

Proste, czyste, bez obejść. Upewnij się tylko, że nie zapomnisz odstępu między wartościami a operatorem (np. (100%-5px)Spowoduje to przerwanie składni. Ciesz się!

Brian Aderer
źródło
6
Niezłe rozwiązanie. Pamiętaj tylko, aby sprawdzić obsługę przeglądarki: czy mogę używać calc ()
Brett Postin
5
Czy nie zapewniłoby to w rzeczywistości 100% szerokości i wysokości każdego wypełnienia PLUS 5px, ponieważ wypełnienie skutecznie zwiększyłoby odpowiednio i szerszy i większy element 10px?
Wreszcie dobre rozwiązanie, a nie jak reszta tam, wrzucisz górną, prawą, dolną i lewą wartość 0, która będzie działać tylko z pozycją: absolutną;
Gil Epshtain
Myślę, że poprawne jest: #myDiv {width: calc (100% - 10px); wysokość: oblicz (100% - 10 pikseli); wypełnienie: 5 pikseli; } 5 od lewej i 5 od prawej = 10, 5 od góry i 5 od dołu = 10
Chris P
21

Zgodnie ze specyfikacją w3c wysokość odnosi się do wysokości widocznego obszaru, np. Na monitorze o rozdzielczości 1280x1024 pikseli 100% wysokości = 1024 piksele.

min-wysokość odnosi się do całkowitej wysokości strony łącznie z zawartością, więc na stronie, na której treść jest większa niż 1024px min-wysokość: 100% rozciągnie się, aby objąć całą zawartość.

Innym problemem jest to, że dopełnianie i obramowanie są dodawane do wysokości i szerokości w większości nowoczesnych przeglądarek z wyjątkiem ie6 (tj. 6 jest w rzeczywistości dość logiczne, ale nie jest zgodne ze specyfikacją). Nazywa się to modelem pudełkowym. Więc jeśli określisz

min-height: 100%;
padding: 5px; 

To faktycznie da ci 100% + 5px + 5px dla wysokości. Aby obejść ten problem, potrzebujesz pojemnika na opakowanie.

<style>
    .FullHeight { 
       height: auto !important; /* ie 6 will ignore this */
       height: 100%;            /* ie 6 will use this instead of min-height */
       min-height: 100%;        /* ie 6 will ignore this */
    }

    .Padded {
       padding: 5px;
    }
</style>

<div class="FullHeight">
   <div class="Padded">
      Hello i am padded.
   </div
</div>
Alex
źródło
4
@Alex: Ale co sprawia, że ​​div div (Padded) 100% wysokości div div. Z mojego doświadczenia wynika, że ​​po prostu dostaniesz trochę krótkiego diva w większym divie pełnej wysokości.
Lawrence Dol
8

1. Pełna wysokość z padding

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  padding: 50px;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

2. Pełna wysokość z margin

body {
  margin: 0;
}
.container {
  min-height: calc(100vh - 100px);
  margin: 50px;
  background: silver;
}
<div class="container">Hello world.</div>

3. Pełna wysokość z border

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  border: 50px solid pink;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

Naklejki
źródło
7

Jest to jedna z najbardziej idiotycznych cech CSS - muszę jeszcze zrozumieć rozumowanie (jeśli ktoś wie, proszę wyjaśnij).

100% oznacza 100% wysokości pojemnika - do której dodawane są wszelkie marginesy, obramowania i wypełnienie. Zatem nie jest możliwe uzyskanie pojemnika, który wypełnia jego element nadrzędny i który ma margines, ramkę lub wypełnienie.

Pamiętaj też, że ustawienie wysokości jest również niespójne między przeglądarkami.


Kolejną rzeczą, której się nauczyłem, odkąd to opublikowałem, jest to, że procent jest względny względem długości kontenera , to znaczy jego szerokości, czyniąc procent jeszcze bardziej bezwartościowym dla wysokości.

Obecnie jednostki rzutni vh i vw są bardziej przydatne, ale nadal nie są szczególnie przydatne do niczego poza kontenerami najwyższego poziomu.

Lawrence Dol
źródło
Nie ma uzasadnienia, tylko to, co się stało, gdy przeglądarki zaczęły dążyć do spójnego zachowania. Sprawdź książkę wymienioną w mojej odpowiedzi.
Frank Schwieterman
Wybrany za użycie właściwego terminu. Tex i każdy menedżer układu, który widziałem, ma rację, tylko CSS musi być wyjątkowy.
maaartinus
5

Innym rozwiązaniem jest użycie display: table, która ma inne zachowanie modelu pudełkowego.

Możesz ustawić wysokość i szerokość dla rodzica i dodać dopełnienie bez rozwijania go. Dziecko ma 100% wysokości i szerokości minus poduszki.

JSBIN

Inną opcją byłoby użycie właściwości dostosowywania wielkości pudełka. Jedynym problemem w obu przypadkach byłoby to, że nie działają one w IE7.

użytkownik1721135
źródło
4

Inne rozwiązanie: Możesz użyć jednostek procentowych dla marginesów i rozmiarów. Na przykład:

.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

Głównym problemem jest to, że marginesy nieznacznie wzrosną / zmniejszą się wraz z rozmiarem elementu macierzystego. Przypuszczalnie funkcjonalność, którą preferujesz, to pozostawienie marginesów na stałym poziomie, a element potomny będzie się powiększał / kurczył, aby wypełnić zmiany odstępów. W zależności od tego, jak ciasno potrzebujesz wyświetlacza, może to być problematyczne. (Wybrałbym również mniejszą marżę, na przykład 0,3%).

ktbiz
źródło
3

Rozwiązanie z flexbox (działające na IE11): ( lub zobacz na jsfiddle )

<html>
  <style>
    html, body {
      height: 100%; /* fix for IE11, not needed for chrome/ff */
      margin: 0; /* CSS-reset for chrome */
    }
  </style>
  <body style="display: flex;">
    <div style="background-color: black; flex: 1; margin: 25px;"></div>
  </body>
</html>

( Reset CSS niekoniecznie jest istotny dla faktycznego problemu).

Ważną częścią jest flex: 1(w połączeniu z display: flexrodzicem). Co zabawne, najbardziej wiarygodne wyjaśnienie, jakie znam dla działania właściwości Flex, pochodzi z dokumentacji rodzimej dla reagowania, więc i tak się do niej odwołuję :

(...) flex: 1, który mówi komponentowi o wypełnieniu całej dostępnej przestrzeni, równomiernie dzielonej między innymi komponentami z tym samym rodzicem

Putzi San
źródło
2

Przykład Franka trochę mnie zdezorientował - w moim przypadku nie zadziałało, ponieważ nie rozumiałem jeszcze wystarczająco dobrze pozycjonowania. Ważne jest, aby pamiętać, że element nadrzędny kontenera musi mieć pozycję niestatyczną (wspomniał o tym, ale przeoczyłem go i nie było go w jego przykładzie).

Oto przykład, w którym dziecko - z wypełnieniem i ramką - używa bezwzględnego pozycjonowania, aby wypełnić element nadrzędny w 100%. Rodzic używa pozycjonowania względnego, aby zapewnić punkt odniesienia dla pozycji dziecka, pozostając w normalnym przepływie - nie ma to wpływu na następny element „więcej treści”:

#box {
    position: relative;
    height: 300px;
    width: 600px;
}

#box p {
    position: absolute;
    border-style: dashed;
    padding: 1em;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
<div id="box">
  <p>100% height and width!</p>
</div>
<div id="more-content">
</div>

Przydatny link do szybkiego uczenia się pozycjonowania CSS

Peter Tseng
źródło
0

Obramuj div, a nie margines treści strony

Inne rozwiązanie - chciałem tylko prostą ramkę wokół krawędzi mojej strony i chciałem 100% wysokości, gdy zawartość była mniejsza.

Border-box nie działał, a ustalone pozycjonowanie wydawało się złe dla tak prostej potrzeby.

Skończyło się na dodaniu ramki do mojego kontenera, zamiast polegać na marginesie strony - wygląda to tak:

body, html {
    height: 100%;
    margin: 0;
}

.container {
    width: 100%;
    min-height: 100%;
    border: 8px solid #564333;
}
Kris Randall
źródło
0

Jest to domyślne zachowanie display: blockNajszybszym sposobem, aby to naprawić w 2020 r. Jest ustawienie display: 'flex'elementu nadrzędnego i wypełnienia, np. 20 pikseli, wtedy wszystkie jego dzieci będą miały 100% wysokości w stosunku do wysokości.

Freestyle09
źródło
0

Dodanie -webkit i -moz byłoby bardziej odpowiednie

-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
użytkownik3113626
źródło
-2
  <style type="text/css">
.stretchedToMargin {
    position:absolute;
    width:100%;
    height:100%;

}
</style>
Mujassir Nasir
źródło