CSS3 box-size: margin-box; Dlaczego nie?

139

Dlaczego nie mamy box-sizing: margin-box;? Zazwyczaj, kiedy umieszczamy box-sizing: border-box;w naszych arkuszach stylów, naprawdę mamy na myśli ten pierwszy.


Przykład:

Powiedzmy, że mam układ strony z 2 kolumnami. Obie kolumny mają szerokość 50%, ale wyglądają trochę brzydko, ponieważ nie ma rynny (luka w środku); Poniżej znajduje się CSS:

.col2 {
    width: 50%;
    float: left;
}


Aby zastosować rynnę, możesz pomyśleć, że możemy po prostu ustawić prawy margines na pierwszej z 2 kolumn; coś takiego:

.col2:first-child {
    margin-right: 24px;
}

Ale to spowodowałoby zawinięcie drugiej kolumny do nowego wiersza, ponieważ jest prawdziwe:

50% + 50% + 24px > 100%

box-sizing: margin-box;rozwiązałoby ten problem poprzez uwzględnienie marginesu w obliczonej szerokości elementu. Uważam to za bardzo przydatne, jeśli nie bardziej przydatne niż box-sizing: border-box;.

Projektant stron internetowych
źródło
30
"Dlaczego nie mamy box-sizing: margin-box;?" Ponieważ chociaż marginesy poziome się nie załamują, taka propozycja poważnie kolidowałaby z załamaniem marginesów pionowych. W każdym razie, jeśli chcesz zaproponować coś do standaryzacji, Stack Overflow nie jest właściwym miejscem. Wypróbuj listy mailingowe.
BoltClock
16
W niektórych sytuacjach możesz to obejść, używając border: xxx solid transparent;, ponieważ granica jest uwzględniona w border-box. To jednak zepsuje kilka innych rzeczy, takich jak box-shadow.
Nathan Osman
28
Czy zamykamy teraz wszystkie pytania dotyczące standardów jako „niekonstruktywnych”? To uczciwe pytanie, a nawet ma na nie prostą odpowiedź: nie mamy, box-sizing: margin-boxponieważ nie działałoby to z zapadaniem marginesów.
thomasrutter
@thomasrutter: Nie było lepszego sformułowania powodu, dla którego to zamykałem, czyli ponad rok temu. W każdym razie „nie konstruktywne” teraz zniknęło (czyli nie, właściwie nie zamykamy już niczego jako niekonstruktywnego), a ponieważ całe „Mam pomysł, oto jak to działa, zróbmy z tego standard!” coś zostało usunięte od czasu ostatniego zamknięcia, teraz brzmi to jak praktyczne "dlaczego X nie może działać?" pytanie. Wciąż jest to niezwykle spekulatywne pytanie (moje rozumowanie powyżej jest tak naprawdę niczym więcej niż wyuczonym przypuszczeniem), ale nie będę dalej komentował tego.
BoltClock
dlaczego nie mieć po prostu wewnętrznego zawijania / div, jeśli chcesz mieć odstępy: codepen.io/chriscoyier/pen/eGcLw
ashley

Odpowiedzi:

55

Nie mógłbyś użyć width: calc(50% - 24px);dla swoich cols? Następnie ustaw marginesy.

Ciamajda
źródło
5
W dużym stopniu zależy od przeglądarki. Prawdopodobnie około 2020 roku ie15 będzie go obsługiwał i będziesz mógł to wykorzystać również w swojej pracy :-(
peterh - Przywróć Monikę
1
Wydaje się, że nie działa tak dobrze w Firefoksie? (albo coś innego, co zrobiłem, nie jest)
Laurengineer
@Morgan Feeney: Tak, ale rozmiar pudełka nie ma wartości zwanej margin-box (o to właśnie chodzi w tym pytaniu). Nawet jeśli taka wartość została wprowadzona teraz, jak proponujesz łatanie / wypełnianie / dopasowywanie jej do istniejących przeglądarek?
BoltClock
Tak, ale ... konkretnie odpowiadając na odpowiedź sugerującą użycie funkcji Calc () jako obejścia.
Morgan Feeney
Nie jestem pewien, czy odnosi się to do konkretnego przykładu, ale głównym minusem użycia funkcji calc () w naszym scenariuszu (jak w FF 53.0.3) jest to, że jego zachowanie nie jest analogiczne do zachowania width: X%; Z tego, co widzimy, "calc" jest wykonywane w momencie początkowego renderowania do statycznego Xpx. Oznacza to, że w przeciwieństwie do width: X%, obliczona kolumna nie zmienia rozmiaru automatycznie wraz ze zmianą rozmiaru kontenera.
Pancho,
16

Myślę, że moglibyśmy mieć box-sizing: margin-box . Model css box pokazuje dokładnie, jakie są pozycje marginesów ramek.

Występują drobne problemy - na przykład pola marginesów mogą się nakładać - ale nie są one trudne do rozwiązania.

Myślę, że sytuacja jest taka sama, jak widać z kombinacjami overflow-x& overflow-y, z absolutnie pozycjonowanymi elementami div w komórkach tabeli, z kombinacją min | max-width | height z wielkością pudełka i tak dalej.

Istnieją funkcje, naprawdę proste funkcje, których programiści przeglądarek po prostu nie rozwijają.

IMHO, box-sizing: margin-boxbyły bardzo przydatną funkcją. Inną przydatną funkcją był box-sizing: padding-box, który istnieje przynajmniej w standardzie, ale nie został zaimplementowany w żadnej z głównych przeglądarek. Nawet w najnowszym chrome!


Uwaga: komentarz @Oriol: Firefox zaimplementował box-sizing: padding-box. Ale inni tego nie zrobili i został usunięty ze specyfikacji. Firefox usunie go w wersji 50. Smutne.

peterh - Przywróć Monikę
źródło
2
Firefox zaimplementował box-sizing: padding-box. Ale inni tego nie zrobili i został usunięty ze specyfikacji. Firefox usunie go w wersji 50. Smutne.
Oriol
6

Facet na górze pyta o dodanie marginesu do całkowitej szerokości, w tym dopełnienia i obramowania. Chodzi o to, że margines jest stosowany poza ramką, a dopełnienie i obramowanie nie, gdy używaszborder-box .

Próbowałem zrealizować ten border-marginpomysł. Odkryłem, że używając marginesu, możesz dodać klasę .lastdo ostatniego elementu (z marginesem, a następnie zastosować margines zerowy lub użyć:last-child/:last-of-type ). Lub dodaj równe marginesy dookoła (podobnie jak w powyższej wersji wypełnienia).

Zobacz przykłady tutaj: http://codepen.io/mofeenster/pen/Anidc

border-boxoblicza szerokość elementu + jego wypełnienie + jego obramowanie jako całkowitą szerokość. Więc jeśli masz 2 divsekundy, które mają 50% szerokości, będą sąsiadować. Jeśli dodasz 8pxdo nich wypełnienie, będziesz miał rynnę 16px. Połącz to z elementem do owijania - który również ma wyściółkę 8px- otrzymasz ładnie ułożoną kratkę z równymi rynnami dookoła.

Zobacz ten przykład tutaj: http://codepen.io/mofeenster/pen/vGgje

Ta ostatnia to moja ulubiona metoda.

Morgan Feeney
źródło
4

Jestem pewien, że to wszystko jest oczywiste, ale i tak to napiszę, ponieważ ... cóż, potrzebuję ćwiczenia. Czy następujący wynik nie byłby tak skuteczny, jak box-sizing: margin-box;:

.col2 {
    width: 45%;
    height: 90%;
    margin: 5% 2.5%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    float: left;
}

http://jsfiddle.net/Fg3hg/

box-sizingsłuży do kontrolowania, od którego punktu wypełnienie i obramowanie są oceniane w stosunku do całkowitego rozmiaru elementu. Więc chociaż nie jest koszerne dołączanie pxmarginesów o %szerokości (jak to zwykle bywa), łatwiej jest obliczyć, jaka powinna być względna wartość procentowa, ponieważ nie musisz uwzględniać dopełnienia i obramowań na zdefiniowanej szerokości.

Plummer
źródło
9
Przykładem użycia czegoś takiego jak pole marginesów jest umożliwienie mieszania szerokości procentowych z marginesami pikseli. Jeśli chcesz mieć dwa 50% pola z marginesem 1 piks. Między nimi, nie można tego osiągnąć z marginesem procentowym 1% podobnego - niektóre małe rozmiary ekranu zaokrągla 1% w dół do 0 pikseli i nagle nie masz marginesu. To, czego naprawdę potrzebujemy, to większa obsługa funkcji calc () w przeglądarce, jak pokazuje @Slouch, lub model flexbox.
1
Jeśli o to chodzi, kontener nadrzędny byłby mniejszy niż 100 pikseli i mam nadzieję, że w tym momencie niektóre elementy projektu zostaną ponownie przemyślane. Jest kilka innych rzeczy, które możesz zrobić z elementami zagnieżdżonymi i tym podobnymi, ale tak, obliczenia zmiennych byłyby całkiem niezłe. Jeśli lubisz takie rzeczy jak sass lub mniej, myślę, że robią wiele takich rzeczy. Bawiłem się nimi, ale nie jestem jeszcze Jedi.
Plummer
2
To, co sugerujesz, to obejście. Nie jest to idealny sposób pisania CSS podczas pracy ze złożonymi układami. Zakładasz, że projektant lub autor chce użyć procentów w swoim projekcie. Niezależnie od tego problemu, nawet jeśli używasz funkcji calc () do obliczania odstępów za pomocą marginesów pikseli, nadal ogranicza to projektanta, ponieważ musi on z góry określić, czym jest rynna, zamiast pozwalać na jej nadpisanie za pomocą CSS.
nieograniczona
Nie rozumiem twojego punktu. Problem polegał na tym, że uwzględnienie px i% powoduje podziały wierszy, ponieważ margines nie jest uwzględniany w obliczaniu rozmiaru. Margines nie jest wliczany w rozmiar elementu, jest to przestrzeń, w której chcesz pojawić się wokół elementu. Poza tym, jak margin-boxporadziłby sobie z wielowymiarowymi obliczeniami depozytu zabezpieczającego? @mediapunkty przerwania max-widthi min-widthdziała dobrze. Wydaje mi się, że margin-boxmoże zmniejszyć niektóre wzdęcia, ale mam też powody, dla których można je uznać za zbędne.
Plummer
Dlaczego nikt nie wspomina, że ​​ten margines procentowy WARTOŚĆ jest procentem szerokości z jakiegoś powodu ... nie ma znaczenia ani wysokość, ani szerokość. Używana jest szerokość elementu nadrzędnego. Co jest co najmniej dziwne ... więc powyższy kod nie powinien działać i nie działa. chyba że zrównasz wysokość i szerokość.
Muhammad Umer
4

Dzieje się tak, ponieważ atrybut box-sizing odnosi się do rozmiaru elementu po obliczeniu podanych wartości specyficznych dla wymiaru (dopełnienie, obramowanie). "box-sizing: border-box" ustawia wysokość / szerokość elementu i bierze pod uwagę dopełnienie oraz szerokość obramowania. Zakres marginesu elementu jest większy niż sam element, co oznacza, że ​​modyfikuje przepływ strony i otaczających ją elementów, a tym samym bezpośrednio zmienia sposób, w jaki element pasuje do jego elementu nadrzędnego w stosunku do elementów siostrzanych. Ostatecznie wartość atrybutu „margin-box” spowodowałaby poważne problemy i jest zasadniczo taka sama, jak bezpośrednie ustawienie wysokości / szerokości elementów.

Ryan
źródło
1
przepraszam, ale nie rozumiem, w jaki sposób uwzględnienie dopełnienia, obramowania i marginesu w obliczeniach przestrzennych za pomocą „pola marginesu” różni się koncepcyjnie od uwzględnienia dopełnienia i obramowania za pomocą „pola obramowania”. Z pewnością to tylko wariacja na ten sam temat?
Pancho,
1

W Codrops jest kilka dobrych artykułów na temat wpływu marginesów i wymuszonego przepełnienia wiersza. Sugerują użycie jednostki rem lub em z normalizatorem css ustawiającym rozmiar czcionki na 100% dla wszystkich przeglądarek, a następnie po ustawieniu szerokości i marginesów łatwo jest śledzić wpływ na szerokość wiersza, po prostu robiąc notatkę w komentarzach dla całkowita szerokość. Konwersja 16px na 1 em to sposób na obliczenie łącznej liczby wyświetlanych obszarów docelowych.

Pracując w ten sposób przynajmniej na etapie deweloperskim, a następnie, jeśli potrzebujesz „responsywnych” szablonów, możesz przekonwertować szerokości na%, w tym szerokości marginesów.

Innym i często prostszym sposobem radzenia sobie z rynnami jest użycie pseudo po i content: '';na każdej z twoich kolumn, które, jak uważam, działają naprawdę dobrze. Jeśli ustawisz klasę div, która jest zdefiniowaną jako ostatnia kolumna, na przykład end, możesz tak ustawić klasę, aby nie miała po niej pseudo, lub aby miała szerszą; który kiedykolwiek najlepiej pasuje do Twojego układu.

Dodatkową zaletą korzystania z tej metody pseudoelementu jest to, że daje ona również cel dla cieni, które mogą dać efekt 3D i większą głębię płaskiemu obrazowi na monitorze czytnika. W tej chwili eksperymentuję z tym efektem, zwiększając efekty używane na przyciskach, „poprawiając” gradienty i indeks Z.

Weedy101
źródło
1

Wymiary blokowych, niewymienionych elementów w normalnym przepływie muszą spełniać

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = szerokość zawierającego bloku

W przypadku nadmiernego ograniczenia przeglądarki muszą dostosować lewy lub prawy margines. Myślę, że oznacza to, że szerokość pola marginesu musi być równa szerokości bloku zawierającego (tj. 100%).

W Twoim przypadku przezroczyste obramowania box-sizing: border-boxmogą działać podobnie jak marginesy .

sam
źródło
1

Być może ustaw obramowanie na 0% krycia za pomocą RGBA i użyj obramowania jako marginesu.

user3236407
źródło
Brzmi jak włamanie, ale wystarczyłoby.
Morgan Feeney
Może się to okazać przydatne, jeśli nie chcesz używać opakowań do wykonania zadania.
nieograniczona
... chyba że faktycznie potrzebujesz granicy
FrancescoMM
@FrancescoMM - trochę "hałaśliwe", ale możesz zrobić ramkę z przezroczystą ramką o szerokości marginesu (i oczywiście bez marginesu) i wewnątrz tego umieścić ramkę z widoczną ramką o szerokości, którą chcesz wyświetlić (ponownie nie mając margines)
Pancho,
1
Po prostu nie mogę podążać za takim sposobem myślenia. Czy jest coś bardziej naturalnego niż stwierdzenie, że chcę 1pxrozdzielić dwa pudełka , z których każde zajmuje 50%dostępną przestrzeń? Dokładnie to margin-boxby zrobił. Lub zapomnij o marginesie i pomyśl o dostępnej przestrzeni. Nie 50% kontenera nadrzędnego, ale 50% tego, co zostało. Bez "kalkulacji", bez "5% marży", bez bałaganu ...
maaartinus
0

Ciekawa sytuacja występuje przy używaniu rozmiaru pudełka w treści ciała

no content no border box nie daje żadnej wartości na lewym-prawym marginesie% recount of this two box recount algoritms

  .body{
    box-sizing: border-box;
    margin:0 3%;
  }

Wersje przeglądarki Firefox starsze niż 57 również obsługiwały wartość padding-box dla rozmiaru pola, chociaż ta wartość została usunięta ze specyfikacji i późniejszych wersji przeglądarki.

Więc margines nawet nie jest planowany ...

Dmytro Yurchenko
źródło