Огляд HasLayout
Оригінал: http://msdn.microsoft.com/en-us/library/bb250481(VS.85).aspx
Переклад: Влад Мержевич
Що таке HasLayout і чому він важливий?
Деякі помилки в Internet Explorer можна уникнути, встановивши для елемента "лейаут". Більшість користувачів не усвідомлюють значення "лейаута", застосованого до елементу. Цей документ пояснює, що відбувається, коли елемент має "лейаут" і наслідки цього.
Почнемо з того, що є два набори елементів.
- Елементи, які залежать від батька для визначення розмірів та упорядкування їх вмісту.
- Елементи, які відповідають за розміри та упорядкування власного вмісту.
У основному, елементи в Internet Explorer не відповідають за організацію самих себе. Тег <div> або <p> може мати положення, як у вихідному коді та потоці документа, але їх вміст упорядковує найближчий предок з лейаутом (зазвичай <body>). Такі елементи залежать від предка, щоб він виконав для них увесь важкий процес по визначенню розміру та одиниць виміру.
Елемент, який відповідає за розміри та розташування елементів, може бути предком, а не лише безпосереднім батьком. Основною перевагою кожного елемента, у якого немає власного лейауту, є продуктивність та простота.
Отже, що означає "має лейаут"?
- У короткому вигляді, включення лейауту означає, що елемент відповідає за розміри та позиціонування самого себе і можливо будь-яких дочірніх елементів (якщо дочірній елемент має власний лейаут, то він визначає розміри).
- Деякі "фіксовані" елементи, іншими словами, які мають обмеження розміру завжди мають лейаут. Наприклад, кнопки, зображення, поля форм, теги <select> та <marquee> завжди мають початковий розмір, якщо ширина та висота не вказані явно.
- Іноді елементи, яким зазвичай не потрібна інформація про лейаут, наприклад <div> або <span>, можуть мати специфічні властивості, що встановлюють лейаут для застосування деяких параметрів - наприклад, елемент повинен мати лейаут, щоб отримати смуги прокрутки.
- Як тільки лейаут застосовується, встановлюється прапор hasLayout. Ця властивість повертає true при зверненні до неї.
Чому лейаут так важливий?
- Він обмежує елемент прямокутною формою. Це означає, що вміст елемента не може проходити навколо інших блоків. Наприклад, плаваючі елементи не можуть виходити за межі елементів з лейаутом.
- Для елементів з лейаутом можна встановити новий контекст форматування блоку (див. п. 9.4.1 специфікації CSS 2.1).
- Оскільки лейаути це додаткові об'єкти з інформацією про кешування, а також беруть участь в алгоритмі обчислення розмірів та позиціонування, вміст лейаута обходиться не дешево - це призводить до збільшення використання пам'яті та може призвести до зниження продуктивності.
- Є також побічний ефект авторозміру - елемент з лейаутом неможливо зменшити до розмірів дочірнього елемента. Наприклад, абсолютно позиціонований блок навколо елемента з лейаутом не вдасться зробити меншим за дочірній елемент.
- Прямокутник лейаута підганяється під розмір контенту (помилка з висотою в IE6).
- Багато людей використовують лейаут для обходу багів IE, зокрема з відносним позиціонуванням елементів. Однак відносно позиціонованим елементам не потрібен лейаут, у цьому випадку побічні ефекти можуть призвести до появи проблем.
Які елементи завжди мають лейаут?
- Зображення.
- Таблиці, їх рядки (<tr>) та комірки (<td> та <th>).
- <hr>.
- Елементи форм: текстові поля, кнопка, поле з файлом, <select>.
- <marquee>.
- <frameset>, <frame>.
- <object>, <applet>, <embed>.
- Абсолютно позиціоновані елементи.
- Плаваючі елементи.
- Рядково-блочні елементи.
- Фільтри (rotation, dropshadow та ін.).
- <body> (а також <html> в строгому режимі).
Які елементи можуть отримати лейаут?
- Блочні елементи з width або height в строгому режимі.
- Будь-який елемент з вказаним width або height в режимі сумісності.
- Елемент, у якого встановлено властивість zoom.
- Елементи в режимі редагування.
- Елементи, які приймають поведінку viewlink.
- У яких порядок виведення відрізняється від батьківського (справа наліво замість зліва направо).
Значення HasLayout
За цим посиланням міститься список відомих обхідних шляхів, які встановлюють лейаут без візуальних змін. Якщо ви бачили або використовували їх, знайте та про наслідки.
Сценарій 1. Обтікання
Давайте розглянемо наступний код
Що ми очікуємо?
- Текст красиво обтікає навколо лівого плаваючого <div>, як і очікувалося.
- Межа демонструє схему блоків навколо <span>.
Що станеться, коли ми застосуємо лейаут до <span> з текстом?
Результат виглядає тепер так.
- Застосування лейауту встановлює <span> як прямокутний блок.
- Текст більше не обтікає навколо <div>. Це дуже важливо, оскільки руйнує очікувану поведінку розмітки тексту (уявіть, що ви застосували лейаут до тегу <p>).
Сценарій 2. Авторозмір
Чого ми очікуємо?
- Перший <div> позиціонується абсолютно, пов'язаний з блоком контенту та виведений з потоку.
- Червоний фон розташовується навколо "123", оскільки він визначений батьком абсолютно позиціонованого <div>.
Що станеться, якщо застосувати лейаут до <div> з "123"?
Результат виглядає тепер так.
- <div> тепер має власний лейаут і повністю ігнорує всі "вимоги" батька.
- Ми повністю втратили поведінку "обгортки", ініційовану батьком. Це побічний ефект, про який ви повинні знати, застосовуючи лейаут до елементу.
Сценарій 3. position: relative
Давайте зараз розглянемо приклад, в якому hasLayout використовується для обходу помилки.
Ми очікуємо, що IE надасть наступний результат.
Должно це виглядати наступним чином.
У IE6 нас чекає сюрприз.
Що сталося?
- Зображення, як відносно позиціонований елемент, залежить від батька, який повинен визначити, де його розмістити.
- У <div> з <float> встановлено hasLayout.
- У IE6 код для вимірювання відносного позиціонування дуже крихкий (це баг і він виправлений в IE7) і батько робить помилку в вимірюванні зсуву зображення.
Традиційно, спробуємо вирішити цю проблему встановленням лейауту.
Результат тепер виглядає наступним чином.
Добре
- Ваше зображення тепер там, де і повинно бути (лейаут верхнього рівня встановив правильне положення плаваючого елемента та зображення).
Погано
Лейаут <div> має тепер небажані побічні ефекти:
- Синя межа більше не згортається, як повинна, лейаут тепер охоплює зображення та плаваючий елемент.
- Будь-який текст, який обтікає плаваючий елемент, буде блочним.
- Витрати продуктивності цього сценарію невеликі, але якщо на сторінку помістити їх 50... ви отримаєте крапку.
В цьому