CSS’ні бокси

Перед тим, як починати поширюватися про те, як CSS’ом розкладати на екрані частини веб-сторінки, я хочу обов’язково розповісти, з чого складається базова екранна одиниця, якою оперує CSS – бокс.

Сутність боксу

Всі елементи веб-сторінки – фактично все, що обмежене будь-якими тегами – представляється в CSS прямокутними областями, які якраз і називаються боксами. Наприклад, у такій ось сторінці:

<body>
<h1>Заголовок</h1>

<p>Абзац</p>
</body>

… елемент body становить один бокс, в нього вкладаються бокси елементів h1 і p.

Насправді, навіть усередині h1 і p організовуються свої бокси для кожного рядка тексту, але це хащі, і зараз я про це поширюватися не буду.

Бокси володіють двома очевидними властивостями:

  • Вони можуть вкладатися один в одного
  • У них є розміри

Вкладення боксів один в одного, а також вилучення одних з інших буде обговорюватися в наступних статтях про розкладку, а ось з приводу розмірів я якраз і хочу поговорити окремо.

Розмір будь-якого боксу складається з ширини і висоти області вмісту, відступів, товщини рамок та кордонів. Наочно це виглядає так:

Опишу сенс всіх частин боксу (заодно зауважу, що перераховані назви, взагалі кажучи, маловідомі, і частіше замість них використовують англійські терміни):

По-українськи По-англійськи Сенс
область вмісту content area тут розташовується вміст боксу: текст та інші вкладені в нього бокси
ширина width
висота height
відступи padding відступ від невидимих кордонів вмісту до рамки, на нього, до речі, поширюється фон боксу, якщо він є
рамка border рамка навколо вмісту, яка, крім декоративного ефекту, теж впливає на розмір всього боксу через свою товщину
кордони margin відступи від рамки до інших, зовнішніх боксів

Засідка

У CSS прийнято, що при вказівці розмірів областей боксу, відступи, товщина рамки і межі додаються до розмірів області вмісту. Звучить логічно? На зразок того … Візьмемо такий шматок HTML’а:

<body>

   <h1>Гарний загловок на синьому фоні</h1>

І тепер ми хочемо, щоб заголовок був, власне, на синьому фоні, займав по ширині весь доступний простір, а навколо нього був білий простір, скажімо, в 10 пікселів:

h1 {
  width:100%;
  margin:10px;
  color:white; background-color:blue;
}

Синтаксис, думаю, пояснювати не треба, він очевидний. Так от, якщо ми подивимося на результат у браузері, що правильно обробляє ці самі бокси, то побачимо таке:

Явно не те, що хотілося: заголовок для чогось поїхав за правий край, та ще й скроллбар з’явився, який не прибирається, як вікно ні розтягуй. Це не глюк. Це відбувається як раз від того, що кордони – по 10 пікселів з кожного боку – додалися до тієї ширині, яку ми вказали – 100%. І загальний розмір всього боксу тепер завжди буде по ширині на 20 пікселів більше того, в якому він лежить («контейнера»).

Про цей ефект необхідно пам’ятати весь час, коли ви розкладаєте щось CSS’ом, тому що він, взагалі-то, не зовсім інтуїтивно зрозумілий. Мені, пам’ятається, набагато частіше хотілося, щоб було можна навпаки: задати граничні розміри якогось боксу, щоб він точно вмістився, куди треба, а вже всередину робити всілякі відступи. Однак, це, все ж, не помилка розробників стандарту. Є також чимало випадків, коли така поведінка необхідна. Наприклад, якщо у вас є картинка з заданими розмірами, і ви хочете навколо неї невеликий відступ і рамочку, то ви хочете їх саме навколо, а не щоб вони влізли всередину картинки і стиснули зображення.

Практичний нюанс

Цю частину, в принципі, можна пропустити, якщо для вас ця тема в новинку, тому що вона здатна внести якусь плутанину. Я буду ще сюди обов’язково посилатися, коли справа зовсім дійде до практики…

Просто лише пам’ятати про таку поведінку розмірів боксу мало. На практиці доводиться ще й боротися з браузером Internet Explorer (для Windows) версій 5 і 6. Історично склалося так, що розробники 5-ї версії IE реалізували розрахунок розмірів боксу виходячи саме з людської інтуїції, а не з стандарту (і в цій версії приклад з синім заголовком виглядає саме як замислювалося). До 6-ї ж версією вони цю помилку виправили, але виправили не кардинально, а зробили два режими роботи браузера: один, сумісний зі своєю старою версією, а інший – сумісний зі стандартом. Все ж таки нові браузери (наскільки я знаю, без винятків) працюють саме за стандартним алгоритмом.

Як ви вже зрозуміли, для дизайнера це означає необхідність щось десь підхачувати, що не може не засмучувати. Але таке життя. Я для цього користуюся такими підходами:

  1. Засунути IE5. Незважаючи на радикальність, підхід цілком годиться, якщо ви верстаєте не якийсь дуже відвідуваний комерційний ресурс, куди приходить багато клієнтів з IE5, а більш вузьконаправлений сайт. У таких випадках можна дозволити собі і не підтримувати браузер такої багаторічної давнини.

    Залишається ще IE6. Все, що потрібно зробити, щоб перевести його в стандартний режим – це написати першим рядком HTML-файлу таку штуку:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

    …і він відразу почне малювати бокси, як треба. На сенсі рядка я поки зупинятися не буду, сприймайте це просто як заклинання для включення стандартного режиму рендеринга в IE6.

  2. Не використовувати margin, border і padding одночасно із завданням розміру через width і height. До цього правила, насправді, доводиться часто звертатися незалежно від IE5. Наприклад, якщо ви робите бік з навігаційними меню шириною 100 пікселів і вам хочеться, щоб у нього був красивий відступ всередині в 5 пікселів, то ви просто не можете його поставити, тому що тоді бік буде займати 110 пікселів в ширину і наїде на який-небудь інший бокс, що знаходиться поряд з ним.

    Для цих речей є інші підходи, на них я ще зупинюся детально, коли буду описувати конкретні приклади розкладок.

  3. Якщо все ж таки дуже потрібно змусити IE5 відображати розкладку вірно, то можна вдатися до відомого хаку: Box Model Hack. Тут його наводити не буду. Коротко суть його полягає в тому, що спочатку пишеться більший розмір боксу (з урахуванням поведінки IE5), потім якась хитра нісенітниця, а потім розміри боксу для стандартних браузерів. Фокус у тому, що ця сама нісенітниця сприймається IE5 (і тільки ним – це інший його баг) як початок коментаря, і повторне завдання розмірів він пропускає. Інші ж браузери його бачать і перевизначають перше, неправильне.

***

Це переклад статті. Оригінал тут