Szerokość płynu z równo rozmieszczonymi DIV

329

Mam pojemnik na płyn DIV.

W tym mam 4 DIV-y wszystkie 300px x 250px ...

<div id="container">
   <div class="box1"> </div>
   <div class="box2"> </div>
   <div class="box3"> </div>
   <div class="box4"> </div>
</div>

To, co chcę się wydarzyć, to przesunięcie pola 1 w lewo, pola 4 w prawo i pola 2 i 3 w równych odstępach między nimi. Chcę, aby odstępy były płynne, więc ponieważ przeglądarka jest mniejsza, przestrzeń staje się również mniejsza.

wprowadź opis zdjęcia tutaj

Lee Price
źródło
2
Dlaczego nie zrobić display:inline-block;zamiast float?
ayyp
1
ponieważ IE6 / IE7 obsługuje wyłącznie inline-blockna inlineelementach
Lee Cena
Okej, nie byłem pewien, które przeglądarki wybierzesz.
ayyp
1
Najbliższym rozwiązaniem, jakie mogłem wymyślić, było zawinięcie każdego elementu div .box w inny element div o szerokości 25%. Następnie wyśrodkuj div .box potomka do opakowania. Dywizje .box będą rozmieszczone równomiernie, ale lewy i prawy div nie będą do prawej krawędzi.
Paul Sham
5
Przekształciłem pomysł @Paul Sham w JSFiddle .
Sparky

Odpowiedzi:

440

Zobacz: http://jsfiddle.net/thirtydot/EDp8R/

  • Działa to w IE6 + i we wszystkich nowoczesnych przeglądarkach!
  • Zmniejszono o połowę wybrane wymiary, aby ułatwić pracę.
  • text-align: justifyw połączeniu z .stretchtym, co obsługuje pozycjonowanie.
  • display:inline-block; *display:inline; zoom:1poprawki inline-blockdla IE6 / 7, patrz tutaj .
  • font-size: 0; line-height: 0 naprawia drobny problem w IE6.

#container {
  border: 2px dashed #444;
  height: 125px;
  text-align: justify;
  -ms-text-justify: distribute-all-lines;
  text-justify: distribute-all-lines;
  /* just for demo */
  min-width: 612px;
}

.box1,
.box2,
.box3,
.box4 {
  width: 150px;
  height: 125px;
  vertical-align: top;
  display: inline-block;
  *display: inline;
  zoom: 1
}

.stretch {
  width: 100%;
  display: inline-block;
  font-size: 0;
  line-height: 0
}

.box1,
.box3 {
  background: #ccc
}

.box2,
.box4 {
  background: #0ff
}
<div id="container">
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="box3"></div>
  <div class="box4"></div>
  <span class="stretch"></span>
</div>

Dodatkową span( .stretch) można zastąpić :after.

To nadal działa we wszystkich tych samych przeglądarkach, co powyższe rozwiązanie. :afternie działa w IE6 / 7, ale i tak używają distribute-all-lines, więc to nie ma znaczenia.

Zobacz: http://jsfiddle.net/thirtydot/EDp8R/3/

Ma to niewielką wadę :after: aby ostatni wiersz działał idealnie w Safari, musisz uważać na białe znaki w HTML.

W szczególności to nie działa:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div>
</div>

I to robi:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div></div>

Możesz użyć tego dla dowolnej liczby dzieci divbez dodawania boxNklasy do każdego przez zmianę

.box1, .box2, .box3, .box4 { ...

do

#container > div { ...

Spowoduje to wybranie dowolnego div, który jest pierwszym dzieckiem #containerdiv, i żadnych innych poniżej. Aby uogólnić kolory tła, możesz użyć selektora n-tego rzędu CSS3 , chociaż jest on obsługiwany tylko w IE9 + i innych nowoczesnych przeglądarkach:

.box1, .box3 { ...

staje się:

#container > div:nth-child(odd) { ...

Zobacz tutaj przykład jsfiddle.

trzydzieści
źródło
123
Zajęło mi 3 godziny, aby znaleźć, że powinieneś mieć spacje między każdym polem w html. „Justify” rozszerza spacje między elementami, a jeśli twoja treść <div/><div/><div/>to nie działa. Musisz mieć <div/> <div/> <div/>.
venimus
5
chciałem tylko to zauważyć :), ponieważ trudno jest zauważyć, jeśli pracujesz z wygenerowaną treścią (co jest częstym przypadkiem). Zastanawiałem się justifynad takim przypadkiem, ale dziękuję za dostarczenie działającego rozwiązania. zaoszczędziło mi wielu eksperymentów (pomimo debugowania przez 3 godziny: D). Ponadto mogę dodać notatkę, że jeśli chcesz, aby twój ostatni rząd był wyrównany do lewej, powinieneś dodać dodatkowe niewidoczne pola (aby uzupełnić rząd)
venimus
4
@venimus: Ja napisałem kolejną odpowiedź przy użyciu tej techniki: stackoverflow.com/questions/10548417/... . Co zrobiłeś, aby pozbyć się dodatkowej wysokości spowodowanej dodaniem niewidzialnych skrzynek?
trzydziesty
11
Czy ktoś może wyjaśnić, dlaczego .stretch jest potrzebny?
atp
6
@HartleySan: .stretch/ :afterjest potrzebne, ponieważ (zazwyczaj) z tekstem wyrównanym ostatni wiersz nie jest uzasadniony . Chcemy tutaj, aby ostatnia linia była uzasadniona, stąd potrzeba :after. Co do twojego drugiego pytania, zbadałem to jakiś czas temu w poprzedniej odpowiedzi . W tej odpowiedzi wymagany był JavaScript. Jeśli potrzebujesz obsługi starszych przeglądarek (IE8), uważam, że potrzebujesz JavaScript.
thirtydot
140

Najłatwiejszym sposobem na zrobienie tego jest teraz Flexbox:

http://css-tricks.com/snippets/css/a-guide-to-flexbox/

CSS jest wtedy po prostu:

#container {
    display: flex;
    justify-content: space-between;
}

demo: http://jsfiddle.net/QPrk3/

Jest to jednak obecnie obsługiwane tylko przez stosunkowo nowe przeglądarki ( http://caniuse.com/flexbox ). Ponadto specyfikacja układu Flexbox zmieniła się kilka razy, więc można objąć większą liczbą przeglądarek, dodając dodatkowo starszą składnię:

http://css-tricks.com/old-flexbox-and-new-flexbox/

http://css-tricks.com/using-flexbox/

Ben Jackson
źródło
1
Dziękuję za to, tak łatwo, zastosowałem go do czterech list o równych odstępach w stopce naprawionej na dole strony. Pracowałem przysmak w FF28.0, Chrome 34.0.1847.116 mi IE11.
user1063287
1
Flexbox nie jest najbardziej obsługiwanym narzędziem w Internecie i nie wyprzedza klasycznego podejścia do marginesów i wypełniania.
TheBlackBenzKid
Dla wszystkich, którzy szukają uzasadnienia dla wielu div z nieokreśloną szerokością: użyj flex-wrap z opcją display: flex. Owiń divy o dynamicznej szerokości.
Kamil Budziewski
20

Jeśli css3 jest opcją, można to zrobić za pomocą calc()funkcji css .

Przypadek 1: Wyrównanie pól w jednym wierszu ( FIDDLE )

Znaczniki są proste - kilka div z pewnym elementem kontenera.

CSS wygląda następująco:

div
{
    height: 100px;
    float: left;
    background:pink;
    width: 50px;
    margin-right: calc((100% - 300px) / 5 - 1px); 
}
div:last-child
{
    margin-right:0;
}

gdzie -1px, aby naprawić błąd obliczania / zaokrąglania IE9 + - patrz tutaj

Przypadek 2: Wyrównanie pól w wielu wierszach ( FIDDLE )

Tutaj oprócz calc()funkcji media queriessą konieczne.

Podstawową ideą jest skonfigurowanie zapytania medialnego dla każdego stanu #kolumny, gdzie następnie używam calc () do opracowania marginesu po prawej stronie dla każdego elementu (oprócz tych w ostatniej kolumnie).

Brzmi to jak dużo pracy, ale jeśli używasz LESS lub SASS, można to zrobić dość łatwo

(Nadal można to zrobić za pomocą zwykłego css, ale wtedy będziesz musiał wykonać wszystkie obliczenia ręcznie, a następnie, jeśli zmienisz szerokość pudełka - musisz wszystko jeszcze raz wypracować)

Poniżej znajduje się przykład użycia LESS: (Możesz skopiować / wkleić ten kod tutaj, aby się nim bawić, [jest to również kod, którego użyłem do wygenerowania wyżej wspomnianego skrzypka])

@min-margin: 15px;
@div-width: 150px;

@3divs: (@div-width * 3);
@4divs: (@div-width * 4);
@5divs: (@div-width * 5);
@6divs: (@div-width * 6);
@7divs: (@div-width * 7);

@3divs-width: (@3divs + @min-margin * 2);
@4divs-width: (@4divs + @min-margin * 3);
@5divs-width: (@5divs + @min-margin * 4);
@6divs-width: (@6divs + @min-margin * 5);
@7divs-width: (@7divs + @min-margin * 6);


*{margin:0;padding:0;}

.container
{
    overflow: auto;
    display: block;
    min-width: @3divs-width;
}
.container > div
{
    margin-bottom: 20px;
    width: @div-width;
    height: 100px;
    background: blue;
    float:left;
    color: #fff;
    text-align: center;
}

@media (max-width: @3divs-width) {
    .container > div {  
        margin-right: @min-margin;
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @3divs-width) and (max-width: @4divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{3divs})/2 - 1px)";
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @4divs-width) and (max-width: @5divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{4divs})/3 - 1px)";
    }
    .container > div:nth-child(4n) {  
        margin-right: 0;
    }
}

@media (min-width: @5divs-width) and (max-width: @6divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{5divs})/4 - 1px)";
    }
    .container > div:nth-child(5n) {  
        margin-right: 0;
    }
}

@media (min-width: @6divs-width){
    .container > div {  
        margin-right: ~"calc((100% - @{6divs})/5 - 1px)";
    }
    .container > div:nth-child(6n) {  
        margin-right: 0;
    }
}

Zasadniczo najpierw musisz wybrać szerokość pudełka i minimalny margines, jaki chcesz między nimi.

Dzięki temu możesz obliczyć, ile miejsca potrzebujesz na każdy stan.

Następnie użyj funkcji calc (), aby obliczyć prawy margines, a n-to dziecko, aby usunąć prawy margines z pól w ostatniej kolumnie.

Zaletą tego odpowiedź na odpowiedź przyjętą który wykorzystuje text-align:justifyto, że jeśli masz więcej niż jeden rząd skrzynek - pudełka na ostatnim rzędzie nie dostać „uzasadnione” np: Jeśli istnieją 2 pudełka pozostające w końcowym wierszu - I nie chcę, aby pierwsze pole znajdowało się po lewej stronie, a następne po prawej - ale raczej, aby pola następowały po sobie w kolejności.

Odnośnie obsługi przeglądarki : To będzie działać na IE9 +, Firefox, Chrome, Safari6.0 + - (zobacz tutaj, aby uzyskać więcej informacji) Jednak zauważyłem, że w IE9 + jest trochę usterki między stanami zapytań o media. [jeśli ktoś wie, jak to naprawić, naprawdę chciałbym wiedzieć :)] <- NAPRAWIONO TUTAJ

Danield
źródło
13

Inne posty wspominały o flexboksie , ale jeśli potrzebny jest więcej niż jeden rząd elementów , space-betweenwłaściwość flexboksa zawodzi (patrz koniec postu)

Do tej pory jedynym czystym rozwiązaniem tego problemu jest

Moduł układu siatki CSS ( demo Codepen )

Zasadniczo odpowiedni niezbędny kod sprowadza się do tego:

ul {
  display: grid; /* (1) */
  grid-template-columns: repeat(auto-fit, 120px); /* (2) */
  grid-gap: 1rem; /* (3) */
  justify-content: space-between; /* (4) */
  align-content: flex-start; /* (5) */
}

1) Ustaw element kontenera w kontener siatkowy

2) Ustaw siatkę z „automatyczną” ilością kolumn - w razie potrzeby. Odbywa się to w przypadku responsywnych układów. Szerokość każdej kolumny będzie wynosić 120 pikseli. (Zwróć uwagę na użycie auto-fit(zgodnie z przeznaczeniem auto-fill), które (dla układu 1-rzędowego) zwija puste ścieżki do 0 - pozwalając elementom na rozwinięcie się, aby zająć pozostałe miejsce. (Sprawdź to demo, aby zobaczyć, o czym mówię )).

3) Ustaw odstępy / rynny dla rzędów i kolumn siatki - tutaj, ponieważ chcesz mieć układ „odstępu” - odstęp będzie faktycznie odstępem minimalnym, ponieważ będzie się powiększał w miarę potrzeby.

4) i 5) - Podobne do Flexbox.

body {
  margin: 0;
}
ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, 120px);
  grid-gap: 1rem;
  justify-content: space-between;
  align-content: flex-start;
  
  /* boring properties: */
  list-style: none;
  width: 90vw;
  height: 90vh;
  margin: 2vh auto;
  border: 5px solid green;
  padding: 0;
  overflow: auto;
}
li {
  background: tomato;
  height: 120px;
}
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Demo Codepen (zmiana rozmiaru, aby zobaczyć efekt)


Obsługa przeglądarki - Caniuse

Obecnie obsługiwany przez Chrome (Blink), Firefox, Safari i Edge! ... przy częściowym wsparciu IE (zobacz ten post Rachel Andrew)


NB:

Właściwość Flexbox space-betweendziała świetnie dla jednego rzędu przedmiotów, ale po nałożeniu na elastyczny pojemnik, który otacza jego przedmioty - (z flex-wrap: wrap) - zawodzi, ponieważ nie masz kontroli nad wyrównaniem ostatniego rzędu przedmiotów; ostatni wiersz zawsze będzie uzasadniony (zwykle nie to, co chcesz)

Aby zademonstrować:

Codepen (Zmień rozmiar, aby zobaczyć o czym mówię)


Dalsza lektura na temat siatek CSS:

Danield
źródło
1
Bardzo niedoceniana odpowiedź. To był najprostszy i najskuteczniejszy sposób na osiągnięcie tego, co chciałem zrobić. Dziękuję Ci.
Barnaby Mercer
1
To była najmniejsza ilość CSS (i nie JS!), Która zapewniła dokładnie takie zachowanie, jakiego szukałem, z pewnymi poprawkami pod względem wielkości i przestrzeni.
EKW
1
Szukałem tego przez jakiś czas i w końcu znalazłem! Dzięki @Danield
nareeboy
2

Działa to dla mnie z 5 obrazami w różnych rozmiarach.

  1. Utwórz kontener div
  2. Nieuporządkowana lista obrazów
  3. Na css nieuporządkowane muszą być wyświetlane pionowo i bez kul
  4. Uzasadnij zawartość div div

Działa to z powodu justify-content: space-between i znajduje się na liście, wyświetlanej poziomo.

Na CSS

 #container {
            display: flex;
            justify-content: space-between;
 }
    #container ul li{ display:inline; list-style-type:none;
}

Na html

<div id="container"> 
  <ul>  
        <li><img src="box1.png"><li>
        <li><img src="box2.png"><li>
        <li><img src="box3.png"><li>
        <li><img src="box4.png"><li>
        <li><img src="box5.png"><li>
    </ul>
</div>
Sebastián Brun Valiente
źródło
Chociaż ten kod może dobrze działać, dobrą odpowiedzią byłoby wyjaśnienie, w jaki sposób działa i dlaczego jest dobrym rozwiązaniem.
Blackwood
Warto zauważyć, że flexbox nie jest (lub tylko częściowo) obsługiwany przez IE caniuse.com/#feat=flexbox
David Salamon
czy to reaguje?
stackdave
1

w jQuerywas może kierować bezpośrednio Parent.

TO JEST PRZYDATNE, JEŚLI NIE WIESZ DOKŁADNIE, W JAKI SPOSÓB WIELU DZIECI ZOSTANĄ DYNAMICZNIE DODANE LUB JEŚLI TYLKO NIE MOŻESZ ZNALEŹĆ ICH NUMER.

var tWidth=0;

$('.children').each(function(i,e){
tWidth += $(e).width();

///Example: If the Children have a padding-left of 10px;..
//You could do instead:
tWidth += ($(e).width()+10);

})
$('#parent').css('width',tWidth);

Pozwoli to parentrosnąć poziomo, gdy childrenzostaną dodane beng.

UWAGA: Zakłada się, że '.children'mają one widthi HeightSet

Mam nadzieję, że to pomaga.

ErickBest
źródło
1

Jeśli znasz liczbę elementów na „wiersz” i szerokość kontenera, możesz użyć selektora, aby dodać margines do elementów, których potrzebujesz, aby uzyskać uzasadniony wygląd.

Miałem rzędy trzech div, które chciałem usprawiedliwić, więc użyłem:

.tile:nth-child(3n+2) { margin: 0 10px }

pozwala to środkowej podziałce w każdym rzędzie mieć margines, który wymusza 1. i 3. podziałkę na zewnętrzne krawędzie pojemnika

Doskonały także do innych rzeczy, takich jak kolory tła obramowania itp

Dave Robertson
źródło