Поговорим о margin, он же маргин( часть 2-я )

Эта статья о горизонтальном margin, о том, откуда считаются проценты и что вообще это такое. О вертикальном margin было написанно в прошлой моей статье.Но! Перед тем, как начать…
Читая ваши отзывы к предыдущей статье я решил исправить некоторые недочеты:
  1. Так как некоторые писали, что слово «маргин» «режет» глаз, то именно для них в этой статье будет написано только «margin»
  2. В связи стем, что статья была популярна, я решил в одной статье описать и вертикальный и горизонтальный margin, тем самым повторить предыдущую, чтоб можно было добавить одну статью в «избранное» и не возвращаться к старой
Итак начнем.

Блочная модель
Как вообще работает css на компьютерах?


Допустим в браузер загружен какой-то документ. У любого браузера есть так называемая область просмотра. Это та область, в которой вы наблюдаете содержание, она зависит от разрешения вашего экрана.

Документ по своим размерам может быть любым и никогда не вздумайте подгонять размер документа под размер области просмотра!

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

Так же область просмотра еще называется viewport, а то что загружено браузером — canvas. Эти две области с помощью html связываются через точку привязки origin point, она находится всегда в левом верхнем углу.

НО, это действует только для европейских языков.
В чём проблема?
У нас есть направление текста, слева на право, сверху вниз, поэтому для нас левый верхний угол важен.
Если вы специальными средствами( напр. атрибут dir={ltr | rtl}, где ltr — текст отображается как обычно — слева направо, rtl — текст инвертируется и отображается справа налево ), измените направление вашего приоритета, то увидите, как правый верхний угол станет более приоритетным.

То есть приоритетный угол зависит от направления текста.

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

Преобразование значений

Есть документ, который загрузился, — парсер его преобразовал в «дерево», подлючился css и начинает работать с этим «деревом». При этом, все величины начинаются преобразовываться в px.

Монитор работает с px. Для него em, ex, pt — всё ерунда!

Что монитор можен на этом этапе посчитать?
Всё, что определено размером шрифта( em, ex ), проценты, которые относятся к размерам, которые известны заранее, всё он это перевел в px без учёта области просмотра. Дальше «берет» область просмотра и начинает исходя из её размеров, пересчитывать проценты, которые применяются для размеров.

Например вы поставили div ширина, которого равна width:50%
От чего будут браться эти 50%?
От ширины контейнер, а откуда возьмётся контейнер?
Он определяется шириной области просмотра.

То есть, браузеру сначала нужно понять размер области просмотра, а потом посчитать все проценты. Вот на этом этапе браузер пересчитывает все проценты в px. И на последнем этапе он начинает применять все эти посчитанные проценты, но с учётом своих возможностей, например:

Имеем размер 22,5px, что делать браузеру?
У монитора нету дробных пикселей., поэтому браузер округляет px. В старых IE, в некоторых случаях есть ошибки округления, без учёта области, в которой эти элементы находятся. То есть он будет округлять всегда, без учёта того, что надо эти элементы уместить.

Модель CSS



Любой эелемент, абсолютно любой, можно представить в виде 4-х областей:
  1. margin — внешняя область
  2. border — область рамки
  3. padding — внутренний отступ
  4. область content( для которой задаётся два правила: ширина и высота )
Раньше в базовой модели IE ширина и высота указывалась внешней границе рамки и именно так себя ведёт IE в режиме quirks mode. В этом режиме все IE будут применять ширину и высоту к внешней границе рамки.

Размеры блочных областей



Если ничего не ставить в эти правила — они по-умолчанию становятся в значение auto.
Что это значит?
Если в элементе появляется какой-нибудь контент, то его высота определяется размером контента. а ширина определяется размером контейнера.

Вот теперь поговорим о margin

Margin может проставляться в em, ex, px — жёсткое задание и в % — всегда берется от чего-то.

Margin в % всегда считается от ширины контейнера этого элемента.

Итак, есть 2 блока(div), first и second, second вложен в first.

#first{
padding: 100px;
background:#999;
}
#second{
height:100px;
background:#009;
margin:30% 0 0;
}


И то, что мы можем наблюдать в браузере:


Итак мы видим что margin-top: 30%;
От чего же он считается?
А считается он от ширины контейнера.


Если мы будем уменьшать размеры ширины контейнера, то и margin-top блока #second будет изменяться соответственно:


Итак, margin по-вертикали считается от ширины контейнера

Кроме этого margin может быть отрицательный.

Есть 2 блока, один под другим, верхний — #first, нижний — #second

#first{
height: 200px;
margin: 0 0 100px;
background:#999;
}
#second{
height:200px;
background:#009;
margin:0 100px 0;
}




Пока результат очевиден.
Но, если мы зададим margin: 0 0 -100px;, то элемент по вертикали, позволяет на свою область «заехать» другому элементу или «вылезти» низу своему за пределы своего контейнера.
Вот, что у нас получилось:


Мы видим, что элемент #second «заехал» на элемент #first.
Почему так произошло?
Потому что элемент #second в коде ниже.
А вот теперь будет интересней! :)

Поговорим о Margin Collapsing ( «схлопывание» вертикальных margin ).

Возвращаем прежний код на место( оставляем margin: 0 0 100px; )
Чем определяется Margin Collapsing?
Пример:
второму элементу, тот который у нас #second меняем стили(задаём отступ сверху 50px)

#second{
height:200px;
background:#009;
margin: 50px 100px 0;
}


Многие думают, что сейчас у нас должен появитсья отступ от элемента #first до элемента #second — 150px ( не забываем, что у #first имеет margin: 0 0 100px; а #second только что изменили на margin: 50px 100px 0;.
Но это не так!
Правильный ответ: расстояние между двумя элементами будет 100px, так как 100px > 50px!


Едем дальше.
Изменим наш код:

#first{
height: 200px;
margin: 0 0 -100px;
background:#999;
}
#second{
height:200px;
background:#009;
margin: -50px 100px 0;
}


Поставим элементу #first margin: 0 0 -100px;, а второму эелементу #second margin: -50px 100px 0;
Теперь, как вы думаете, на сколько второй элемент «заедет» на первый?

На 100px !

Для одноименных margin выбирается наибольший по модулю размер.

А вот если мы изменим наш код так:

#first{
height: 200px;
margin: 0 0 -100px;
background:#999;
}
#second{
height:200px;
background:#009;
margin: 50px 100px 0;
}


и элементу #second зададим margin: 50px 100px 0;.
То что у нас произойдет?
А произойдет сложение! То есть, -100px + 50px = -50px. Вот на столько нижний элемент «заедет» на верхний.

Так работает Margin Collapsing для смежных элементов:
  1. Одноименный margin — берется больший по модулю.
  2. Разноименный margin — происходит сложение.

Дальше.

Margin Collapsing наблюдается не только по отношению к смежным элементам.

Есть 2 элемента, один находитсяв другом( #second находится в #first ) и ниже их стили:

#first{
background:#999;
}
#second{
height:200px;
background:#009;
margin: 0 100px 0;
}


И получаем следующую картину:


Так как у второго элемента( внутреннего #second стоит margin: 0 100px 0; ), то мы получили «отжатие» этого элемента слева и права.

А вот теперь указываем ему(внутреннему элементу #second margin: 200px 100px 0;).
Многие ожидают увидеть, что внутренний элемент #second «отодвинется» от границы своего контейнера #first на 200px.
Но это снова неверно!

Вот, что мы получаем на самом деле:


Почему так?
Потому что это одно из следствий Margin Collapsing.

Если у родительского элемента нет ограничивающих факторов( об этих факторах я напишу ниже ), то margin переходит от внутреннего элемента к внешнему, после чего выбирается по старой схеме этот margin ( если одноименные. то выбирается наибольший, для разноименный происходит сложение .)

Теперь, как же остановить этот Margin Collapsing?
  1. Внешнему элементу(#first) поставить border, например border:1px solid black;
  2. Можно добавить padding, например padding:10px;
  3. И последнее правило — overflow(любое значение, кроме visible)

Вот пример, что у нас получилось. я добавил в #first border:1px solid black;

А теперь откываем этот же файл в IE6 и IE7 :)
И видим :)

Но, у них есть такая модель, которая называется layout.
О ней я напишу ниже, а сейчас пока смотрите, что она делает.

Ставим элементу #first свойтсво width:100%(width может быть любым) и вуаля :)

Как это произошло?
А произошло это, за счет модели layout.

Теперь поговорим о горизонтальном margin.

Волшебная формула:

Вот из чего складываются все отдельные части.
Как же рассчитываются margin:auto;?

Представим, что margin не задан, width имеет значение auto, padding — не задали, border — не задал. Что в таком случае произойдет? А вот, что width:auto — рассчитается из ширины контейнера( вот как строится ширина наших div или p )


Напоминаю, что для нас левая сторона имеет больший приоритет, чем правая.
Например: смотрим 1-й пример в таблице: мы задали все три размера.Представим, что ширина контейнера равна 400px, а мы задали width:300px, а margin-left:200px, margin-right:200px;

Что в таком случае получится?
300px + 200px + 200px = 700px
А ширина контейнера, всего, как мы помним - 400px.
Как поступает браузер в такой ситуации?
Он «сбрасывает» margin-right в значение auto и рассчитывает его согласно формуле, то есть:
300px + 200px = 500px и эти 500px вычтит из 400px ( 400px — 500px = — 100px ).
А это значит, что margin-right у нас будет равен -100px.
Вот так.

Отсюда можно сделать вывод: по горизонтали margin участвует в расчете длины элемента, что никогда не делает margin по вертикали, потому что ширина определяется внешним фактором(шириной контейнера), а высота определяется содержанием элементов

Всем спасибо за внимание.
Поделиться

Copyright 2008-2012
Rambler's Top100