Главная » CSS, Статьи и переводы

Равноудаленные элементы

29 Март 2008 просмотров 9 502 комментариев 42


UPD: Есть новый способ! Читайте пункт 4.

Создание равноудаленных друг от друга элементов, находящихся на одной горизонтали, довольно актуальная задача для вебмастеров: кто-то реализует это с помощью таблиц, другие используют css-трюки и т.п. Но так ли сложна задача на самом деле? Рассмотрим подробнее на примере.

Равноудаленные элементы

Наша задача будет в том, чтобы расположить 4 элемента по горизонтали так, чтобы расстояние межу ними было равное и пропорционально изменялось в зависимости от размеров окна браузера. В качестве элементов будем использовать изображения, например круги. Вначале рассмотрим несколько способов, которые чаще всего стараются применить верстальщики и проблемы с которыми они сталкиваются.

1. Определим для каждого элемента ширину в % и позиционируем по левому краю:

<img src="images/shape-red.png" class="first-r">
<img src="images/shape-green.png" class="second-r">
<img src="images/shape-yellow.png" class="third-r">
<img src="images/shape-blue.png" class="fourth-r">

CSS код:

img.first-r { left: 0%; position: relative; }
img.second-r { left: 25%; position: relative; }
img.third-r { left: 50%; position: relative; }
img.third-r { left: 75%; position: relative; }

Важно отметить, что свойство relative должно обязательно присутствовать. Это необходимо для того, чтобы крайний слева элемент позиционировался относительно родительского элемента, если тот имеет центрирование и не прилегает к левому краю. Проблема данного решения заключается в том, что левый отступ самого крайнего элемента справа в 75% отсчитывается от ширины окна браузера, но точкой отсчета будет левый край не окна, а родительского элемента. В результате этого, последний элемент уйдет за пределы экрана, а при определенном размере окна, наша строка и вовсе развалиться.

Если изменить значение relative на absolute, то несколько вышеуказанных проблем вам удастся разрешить и даже добиться равного расстояния между элементами. Но основной проблемой останется то, что все элементы будут иметь позиционирование по левому краю, и правила родительских элементов будут игнорироваться.

2. Определим для каждого элемента (кроме первого) отступ слева:

<span class="do-not-wrap">
<img src="images/shape-red.png">
<img src="images/shape-green.png" class="mover">
<img src="images/shape-yellow.png" class="mover">
<img src="images/shape-blue.png" class="mover">
</span>
img.mover {
margin-left: 15%;
}

Тут нам даже не придется высчитывать отступы для каждого элемента – мы просто зададим общий равный отступ для трех элементов, начиная со второго. По идее все должно работать как надо, т.к. отступ будет отсчитывать от ширины окна браузера, так же как и ширина родительского элемента. также, блок do-not-wrap должен предотвратить разъезжание элементов. Но результат нас опять огорчит…

3. Обернем элементы табличной структурой

<table>
<tr>
<td class="leftalign">
<img src="images/shape-red.png">
</td>
<td>
<img src="images/shape-green.png">
</td>
<td>
<img src="images/shape-yellow.png">
</td>
<td class="rightalign">
<img src="images/shape-blue.png">
</td>
</tr>
</table>

И даже этим способом мы не получим идеального результата – элементы будут равноудалены не всегда. Если задать для 2й и 3ей ячейке центрирование содержимого; крайней слева – по левому краю, и последней по правому краю, то в результате все должно работать как нужно, если… не изменять размеры окна браузера.

4. Что будем делать?

Метод, присланый пользователем hmelii (из комментариев):

Для равноудаленного расположения изображений:

CSS

<style type="text/css">
#movers-row{ text-align:justify}
#movers-row span{ display:inline-block; width:100%; }
</style>

HTML:

<div id="movers-row">
   <img src="http://css-tricks.com/examples/EquidistantObjects/images/shape-red.png" alt="" />
   <img src="http://css-tricks.com/examples/EquidistantObjects/images/shape-green.png" alt="" />
   <img src="http://css-tricks.com/examples/EquidistantObjects/images/shape-yellow.png" alt="" />
   <img src="http://css-tricks.com/examples/EquidistantObjects/images/shape-blue.png" alt="" />
   <span></span>
</div>

Способ работает для всех браузеров! Смотрите пример.

Для равноудаленного расположения блоков:

CSS:

.container {
  text-align: justify;
  text-justify:newspaper;
  width:100%
}
.box{
  display:-moz-inline-box; // для поддержки FF2
  display:inline-block;
  vertical-align:top;
  text-align:left;
  width:200px;
  height:200px;
  background:red;
}
.box p {padding:10px;}
/*IE6*/
* html .box{ display:inline; }

/*IE7*/*
+ html .box{ display:inline; }

.under{display:-moz-inline-box; display:inline-block; width:100%; }

HTML

div class="container">
<div class="box"><p>текст текст текст текст текст</p></div>
<div class="box"><p>текст текст текст текст текст</p></div>
<div class="box"><p>текст текст текст текст текст</p></div>
<div class="box"><p>текст текст текст текст текст</p></div>
<span class="under"></span>
</div>

Способ работает для всех браузеров! Смотрите пример.

Метод Криса Койера

Предыдущий способ навел на некоторые мысли: попробуем позиционировать первый элемент по левому краю, а остальные по правому. Визуально это должно выглядеть так:

Равноудаленные элементы

HTML:

<img src="images/shape-red.png">
<div id="movers-row">
<div><img src="images/shape-green.png"></div>
<div><img src="images/shape-yellow.png"></div>
<div><img src="images/shape-blue.png"></div>
</div>

CSS:

#movers-row {
margin: -120px 0 0 120px;
}#movers-row div {
width: 33.3%;
float: left;
}
#movers-row div img {
float: right;
}

Что ж, смотрим итоги наших попыток реализации равноудаленных элементов. Очевидно, что именно 4й способ и станет идеальным решением.

Материалы статьи: Chris Coyier

Комментариев 42 »

  • ]]>sevon пишет: ]]>

    У вас два третьих пункта подряд =)

      Цитировать

  • ]]>Necronominicon пишет: ]]>

    Спасибо! Ваш совет мне очень помог :)

      Цитировать

  • ]]>FXIX пишет: ]]>



    Может вопрос нубский но “mce_src” – что сие есть?

      Цитировать

  • ]]>Автор пишет: ]]>

    это глюк TinyMice..

      Цитировать

  • ]]>frst пишет: ]]>

    а теперь тоже самое но для элементов разной ширины ;)

      Цитировать

  • ]]>hmelii пишет: ]]>

    У меня есть способ, который Chris Coyier и не снился

      Цитировать

  • ]]>hmelii пишет: ]]>

    Оо Получилось Вот этот способ о котором я говорил Chris Coyier отдыхает вместе со своими идеями

    CSS:

    #movers-row{ text-align:justify}
    #movers-row span{ display:inline-block; width:100%; }
    

    HTML:

    <div id="movers-row">
       <img src="images/shape-red.png" alt="" />
       <img src="images/shape-green.png" alt="" />
       <img src="images/shape-yellow.png" alt="" />
       <img src="images/shape-blue.png" alt="" />
       <span></span>
    </div>
    

      Цитировать

  • ]]>Автор пишет: ]]>

    Решение удивительно простое и необычное, span как бы ложиться под картинки, не давая им развалиться в блоке. И работает во всех браузерах!
    Думаю вам стоит разместить это к статье Криса ;)

      Цитировать

  • ]]>hmelii пишет: ]]>

    Добавлю ещё что этот способ помимо своей простоты имеет ряд достоинств о которых блочный способ и не мечтал Во первых поддержка картинок любого размера Во вторых неограниченное колличество И в третьих самое важно поддержка вертикального выравнивания

      Цитировать

  • ]]>hurum пишет: ]]>

    Если это не картинки, а блоки или абзацы?

      Цитировать

  • ]]>hmelii пишет: ]]>

    К сожалению кроссбраузерного решения для блоков я пока не нашел Мой метод работает только в firefox safari opera и chrome

      Цитировать

  • ]]>hmelii пишет: ]]>

    Привет Это опять я Нашел таки способ и для блочной модели выравнивание во ВСЕХ браузерах (ff2, ff3, opera, safari, chrome и самые любимые ie6, ie7 ) Если интересно могу выложить

      Цитировать

  • ]]>Автор пишет: ]]>

    Выкладывай :) Только код оберни в <pre></pre>, я исправила прошлые баги.

      Цитировать

  • ]]>hmelii пишет: ]]>

    CSS:
    * { margin:0; padding:0;}
    .container { text-align: justify; text-justify:newspaper; }
    .box{ display:-moz-inline-box; display:inline-block; vertical-align:top; text-align:left; width:200px; height:200px; background:red; }
    .box div{ width:200px; height:200px;}
    /*IE6*/* html .box{ display:inline; }
    /*IE7*/* + html .box{ display:inline; }
    .under{display:-moz-inline-box; display:inline-block; width:100%; }
    html:
    <div class="container">

    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>

    <span class="under"><!– –></span>
    </div>

      Цитировать

  • ]]>hmelii пишет: ]]>

    Появился код ? Что скажешь ? Как метод ?

      Цитировать

  • ]]>Автор пишет: ]]>

    Что касается фиксированных размеров блоков, то все работает классно, но если для div.box задать 25%, то во всех браузерах, кроме IE6 и IE7 (на удивление) они разваливаются.. Максимум можно задать 24%. И еще, для чего дополнительно для FF прописывать “display:-moz-inline-box; ” ?

      Цитировать

  • ]]>hmelii пишет: ]]>

    А какой смысл для div.box задать width 25% для 4 боксов Зачем тогда нужно выравнивание ?Если конечно имеешь ввиду для меньшего колличества боксов например для трех То все нормально РАБОТАЕТ Ничего не разваливается Что касается display:-moz-inline-box; То это для ff2 Так он не поддерживает display:inline;blockПоэтому если проекту не нужна поддержка устаревшего ff2 Это свойство можно опустить А также вложенные дивы тоже Код станет проще и валидней !

      Цитировать

  • ]]>Автор пишет: ]]>

    Это я просто проверяла что лучше float:left или твой способ для макетов с блоками равной ширины…
    А вообще классное решение, спасибо! Я в начало статьи помещу :)

      Цитировать

  • ]]>hmelii пишет: ]]>

    Насчет преимущества float боксов с процентной шириной Это ты зря Причем заметь что боксы распологаются в строку без оберток ! Вот реальный пример css
    * { margin:0; padding:0; }
    .container { width:25%; word-spacing:-1px;}
    .box{ display:-moz-inline-stack; word-spacing:normal; display:inline-block; vertical-align:middle; width:25%; background:red; }
    .box div{font-size:12px; }
    .in{ width:400%; }
    /*IE6*/* html .box{ display:inline; }
    /*IE7*/* + html .box{ display:inline; }
    .over{ overflow:hidden; position:relative; font-size:0; }
    html
    <div class="over">
    <div class="container">
    <div class="in">
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст т</div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текстекст текст текст текст текст текст текст текст текст екст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текстекст текст текст текст текст текст текст текст текст екст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    <div class="box"><div>текст текст текст текст т</div></div>
    <div class="box"><div>текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст </div></div>
    </div>
    </div>
    </div>
    А сможет ли так float модель ?

      Цитировать

  • ]]>Автор пишет: ]]>

    Ну не скажи, что без обертки.. все таки 2 дополнительных блока, которые, с позиции семантики, “висячие”, т.к. являются обязательным дополнением, но на дизайне как таковые не оборажаются – такого лушче избегать. Хотя с флоатами конечно ситуация не лучше.

    ..и в IE6 горизонтальная прокрутка появляется (у меня IEtester, а не сам IE6)

      Цитировать

  • ]]>hmelii пишет: ]]>

    Я имел ввиду не эту обертку А ту что обварачивала бы каждые четыре бокса с float Чтобы следующая строка с четырьмя блоками не ломалась в случае если в первой были бы боксы с не равной высотой Щас покажу пример

      Цитировать

  • ]]>Автор пишет: ]]>

    Это я поняла, поэтому и говорю, что и с флоатами не все так идеально.

      Цитировать

  • ]]>hmelii пишет: ]]>

    Вот гляди css:
    * { margin:0; padding:0; }
    .over{ overflow:hidden; display:block!important; /*IE6*/display:inline-block; }
    .box{ float:left; width:25%; clear:right; }
    .box p{ border:1px solid red;}
    html
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>

    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    На первый взгляд все четко но стоит нам в один из боксов добавить чуть текста

    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>

    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    происходит не приятная ситуация И что нам приходится делать Обварачивать каждую четверку в обертку

    <div class="over">
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    </div>

    <div class="over">
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    <div class="box"><p>тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект тект</p></div>
    </div>
    В методе с inline-block Все идет единным потоком ! Насчет тех трех оберток Так это для любимого браузера ie )Другого способа покамест не нашел

      Цитировать

  • ]]>reg пишет: ]]>

    приветствую! такая вот интересная вещь обнаружена, что если убрать все пробелы в данном коде:

    то картинки сдвигаются к друг другу в плотную :(

      Цитировать

  • ]]>reg пишет: ]]>

    что то код не отобразился, видимо что то не так написал.
    код имелся в виду который написал Hmelii. т.е. убрать пробел между скобками.

      Цитировать

  • ]]>hmelii пишет: ]]>

    А зачем ты убрал пробелы? Представь себе если ты уберешь между словами пробелы и определишь для них свойтво text-align:justify Они же не будут отображаться как надо Здесь аналогичный случай Пробелы между необходимы!

      Цитировать

  • ]]>ЛАСТЫЧ пишет: ]]>

    А как быть со спаном? В IE6 он имеет определенную высоту и если у контейнера один фон, а у самих блоков другой то контейнер растягивается. Существует ли какая-либо возможность заменить span чем то другим?

      Цитировать

  • ]]>Автор пишет: ]]>

    Для span дополнительно укажите свойства
    font-size:0px;
    line-height:0px;
    и тогда он не будет иметь высоты.

      Цитировать

  • ]]>Enlightened пишет: ]]>

    Пример Hemlli не работает в Konqueror:)

    http://kompas-studio.ru/files/color_new1.png

    Но, в целом, решение отличное, спасибо.

      Цитировать

  • ]]>Блог для вебмастеров пишет: ]]>

    @Enlightened, к счастью им пользуется ооочень маленький % юзеров :)

      Цитировать

  • ]]>Сергей пишет: ]]>

    Привет.
    метод hmelii

    плохо работает под огнелисом2

    так как все что внутри блока превращается в инлайн

    из этого получается много проблем с размещением элементов внутри

      Цитировать

  • ]]>hmelii пишет: ]]>

    а под первым вообще не работает )))

      Цитировать

  • ]]>Сергей пишет: ]]>

    Да я понимаю что это мрак под него править, но нужно :(

      Цитировать

  • ]]>Сергей пишет: ]]>

    Решил частично проблему взял в див все что внутри флат лефт и хак только для огнелиса2

      Цитировать

  • ]]>hmelii пишет: ]]>

    Привет. У меня к тебе есть одна просьба. Прочитав эту статью http://habrahabr.ru/blogs/css/102651/ , я попробывал реализовать эту задачу способом которым я действовал тут, но немного изменил его. Тем самым избавился от лишнего элемента. Если тебе не трудно, не могла бы ты помочь разместить этот способ на хабре.

      Цитировать

  • ]]>hmelii пишет: ]]>

    В предыдущий раз у меня возникли проблемы с размещением кода, поэтому дам ссылку на пример http://hmelii.ru/example/index.html . И сразу скажу, что есть один недостаток. В браузерах, основанных на webkit, зачем-то отображается пробел после последнего элемента, поэтому пришлось html код писать в одну строку. Работает в ie6, ie7, ie8, safari, chrome ff3, opera10

      Цитировать

  • ]]>hmelii пишет: ]]>

    да и выравнивать можно и по нижней линии и по верхней и по средней, как в примере.

      Цитировать

  • ]]>даник.html пишет: ]]>

    hmelii, офигеть решение ).Кстати, можно span заменить на псевдоэлемент :after. Тогда разметка остается чистой и без лишних пустых элементов. ie7 не понимает :after, но ему можно експрешн подсунуть, или подключить знаменитый IE8.js.

      Цитировать

  • ]]>hmelii пишет: ]]>

    Не нужно експрешн. Читайте мой предпоследний коммент. Я там дал ссылку на новую версию этого метода. Где как раз уже нет лишних элементов. И работает во всех браузерах включая и ie

      Цитировать

  • ]]>Алеусей пишет: ]]>

    Читайте мой предпоследний коммент. Я там дал ссылку на новую версию этого метода. Где как раз уже нет лишних элементов. И работает во всех браузерах включая и ie

    А можно выложить код нового метода!? Спасибо!

      Цитировать

  • ]]>Amir пишет: ]]>

    Второй метод hmelii, это, конечно не метод, а сплошные костыли, хоть и эффективные). Думаю, от него лучше сразу отказаться.

      Цитировать

Комментарии

Добавьте ваш комментарий, или трекбэк с сайта. Вы также можете подписаться на комментарии к этой статье через RSS.

Вы можете использовать теги:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Чтобы получить аватарку, зарегистрируйтесь на Gravatar.