|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CSS-верстка для продолжающихВведениеДля кого этот материалНачну с отрицания — этот материал не для начинающих, и не для тех, кто знакомится с сайтостроением в целях общего развития. Вы уже собираетесь задвинуть его на полку? Не торопитесь, вдруг это именно то, что вам нужно! Предполагается, что читатель умеет размечать страницу тегами HTML, знаком с CSS, но испытывает растерянность на практике. То есть здесь не излагаются темы, связанные с синтаксисом конструкций HTML/CSS, предполагается, что они известны читателю, или он при необходимости способен освежить память по соответствующим справочникам. Здесь излагаются алгоритмы работы базовых конструкций HTML/CSS и прокладывает тропинку от теории к практике (верстке страниц средствами CSS). Материал предназначен в первую очередь для учителей информатики, а также для тех школьников (и студентов вузов), которые рассматривают сайтостроение как элективную (профильную) часть своего образования. Хорошо писать коды, если не нужно гадать, как написанное отобразится на экране, и удивляться, когда ожидания не оправдываются. Хорошо, когда все предсказуемо. Хорошо, когда на любой возникший вопрос (свой, ученика или товарища) можно дать внятный ответ. Когда поведение браузера известно, коды предсказуемо отображаются в голове и на экране. Это и есть основная цель — дать читателю определенность и избавить его (по возможности) от лишней головной боли. Структура книги и перекрестные ссылкиСодержание книги охватывает три темы (разделы “Введение” и “Ссылки” не в счет): Введение Тема 1. Верстка потоком Тема 2. Позиционирование Тема 3. Плавающие блоки Ссылки В разделе “Тема 1. Верстка потоком” приводятся алгоритмы работы браузера по умолчанию. В разделе “Тема 2. Позиционирование” рассмотрена верстка при помощи блоков, размещаемых в заданных координатах. Раздел “Тема 3. Плавающие блоки” демонстрирует построение страниц при помощи блоков со свойством float Читать книгу рекомендуется по порядку, темы тесно взаимосвязаны, и эта связь подчеркивается перекрестными ссылками, записываемыми в виде: “см. 1.2.4.” — ссылка на раздел первой темы “1.2.4. Устройство строчного элемента”. В последнем разделе “Ссылки” собраны пронумерованные адреса сайтов Интернета, которые упоминаются в основном тексте. Ссылки на эту страницу выглядят так: “ссылка[2]” — определяет вторую запись в разделе “Ссылки”, в ней указан сайт с описанием стандарта HTML 4.1 от W3C (www.w3.org/TR/html401). Гораздо удобнее пользоваться электронной версией этой страницы (см. следующий раздел). Загрузка электронных страницДля удобства читателей все примеры, обсуждаемые здесь, собраны в электронное приложение, которое настоятельно рекомендуется скопировать с адреса: http://inf.1september.ru, раздел “Download”. Разверните скопированную запаковку в пустом каталоге, стартовый файл: index.htm. В бумажной версии ссылки на электронные страницы записаны в виде: “поток/меню на вкладках/шаг 5” — на странице “поток” переходим к разделу “меню на вкладках”, а в нем — к пункту “шаг 5”. Видим запись: Шаг 5: example/01/menu/v05/, index.htm, main.css Щелчок на “Шаг 5” покажет вид обсуждаемого примера на пятом шаге его построения, щелчки на “index.htm” и “main.css” откроют страницы с кодами, а запись “example/01/menu/v05/” сообщает о каталоге, в котором расположены эти коды. Страница “ссылки” в электронном варианте повторяет аналогичную бумажную страницу, и пользоваться ей для переходов гораздо удобнее. CSS-верстка — почему это важно?В конце прошлого века и самом начале нынешнего сайтостроители работали в тяжелых условиях: медленный Интернет ограничивал творческие порывы, а каждый браузер требовал особого программирования. Сейчас времена изменились. Во-первых, медленные аналоговые модемы сменяются быстрыми цифровыми, во-вторых война браузеров наконец закончилась и заменилась позитивной конкуренцией: теперь производители пытаются обогнать друг друга в наиболее полной и точной поддержке стандартов W3C. Иными словами: · скорость Интернета возросла; · браузеры стали поддерживать стандарты. В соответствии с этим дизайнеры по всему миру стали по-другому строить свои сайты. В настоящее время стало наконец возможным изолировать визуальный образ сайта (в файле CSS) от его содержания (в файлах HTML). Такой подход позволяет: · Сократить объем HTML-кода за счет удаления из тегов значительной части атрибутов (сокращение может достигнуть 50%). · Уменьшить время загрузки страниц за счет того, что единственный файл CSS кэшируется браузером. · Упростить работу по изменению внешнего вида сайта. Редактировать придется единственный файл со стилевыми определениями, а не многочисленные файлы с кодами гипертекстовых страниц. · Легко настраивать сайт на разные средства просмотра. · Использовать гораздо больше свойств и значений CSS, чем это было возможно при помощи атрибутов HTML. В заметках, представленных на страницах этой книги, рассматриваются вопросы, связанные с версткой гипертекстовых страниц при помощи CSS. Начинающий сайтостроитель, берясь за свое дело, сразу начинает проклинать браузеры, ругаясь нехорошими словами на их разработчиков. На картинках-ссылках появляются “хвосты”, строчный элемент вылезает за пределы своего родителя, блочный со 100%-ной шириной включает линейку прокрутки… Да, конечно, браузеры содержат ошибки. Но часто то, что принимается за ошибку, является задуманным, задокументированным и логичным поведением.
Вот почему разработчику необходимо знать алгоритмы работы браузера, и заметки раскрывают наиболее важные из них. Шаблон HTML для проверки примеровПримеры на HTML, которые содержатся на бумажных страницах, записаны в сокращенной форме: <BODY>содержимое примера</BODY>. Полный шаблон страницы, в котором работают примеры, должен иметь вид: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML lang="ru">
<HEAD> <META http-equiv="Content-Type" content="text/html; charset=windows-1251"> <META http-equiv="Content-Style-Type" content="text/css"> <STYLE type="text/css">@import url(main.css);</STYLE> <TITLE>Заголовок окна</TITLE> </HEAD>
<BODY> Содержимое примера </BODY>
</HTML> Указана кодировка windows-1251 и проставлена ссылка на файл со стилями main.css. Для DOCTYPE выбран вариант Transitional . Подробнее о декларации DOCTYPE рассказано ниже. ДекларацияDOCTYPEБраузер должен знать, на каком языке написана страница, чтобы правильно отобразить ее на экране (или другом устройстве). Для этого в первой строке кода необходимо записывать конструкцию DOCTYPE.
Очень сильно влияет! Ваша визуальная разметка, выполненная средствами CSS по стандартам W3C, может потерпеть крах на экране, если DOCTYPE не будет записан. Элемент DOCTYPE предназначен для указания соответствия кода документа одному из стандартов W3C. Браузер, в зависимости от стандарта, по-разному интерпретирует элементы на странице. Элемент DOCTYPE — это скорее даже не элемент, а описание (декларация), имеющее свой собственный синтаксис. Декларацию DOCTYPE помещают самой первой (перед элементом HTML), она начинается с восклицательного знака и записывается прописными буквами. Варианты DOCTYPE для HTML 4.01 приводятся ниже. Предусмотрено 3 стандарта языка HTML 4.01: · Strict (строгий) · Transitional (переходный) · Frameset (аналогичен Transitional, но с фреймами) Вариант Strict Код не содержит элементов и атрибутов, помеченных W3C как “устаревшие” или “не одобряемые” (например: CENTER , FONT, S, U, align, background, bgcolor , color, size). Декларация записывается в виде: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> Вариант Transitional Код может содержать устаревшие теги, вариант введен в целях совместимости со старыми версиями HTML. Декларация записывается в виде: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> Вариант Frameset Аналогичен Transitional, но содержит также элементы для создания наборов фреймов. Декларация записывается в виде: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"> Какой вариант DOCTYPE выбрать? Вариант Frameset отбрасываем сразу, так как фреймы — это рудимент прошлого века, и использовать их мы не собираемся. В переходный период, когда браузеры не на 100% поддерживают стандарты, ничего другого не остается для практики, как выбрать переходный стандарт Transitional. Таким образом, код любой нашей странички будет иметь вид: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML lang="ru"> ... </HTML> Атрибут lang со значением ru определяет русский язык в качестве базового языка на страничке.
Спецификация HTML 4.01 (ссылка [2]) Автор
При подготовке иллюстративного материала использованы художественные заготовки, выполненные роботландским художником Александром Артуровичем Руссом. Тема 1. Верстка потоком
Содержание темы1.1. Элементы: блочные и строчные 1.2. Архитектура и поведение элемента 1.3. Размеры и выравнивание 1.4. Проблемы размеров и их решение 1.5. Как работает браузер. Верстка потоком 1.6. Пример построения меню на вкладках 1.1. Элементы: блочные и строчныеИнтересные тексты? Они есть у нас! Заголовок интересного текста Первый абзац. В этом абзаце есть очень важное слово, которое выделено. Второй абзац. В нем приводится небольшая цитата, которая поддерживает изложение. (а здесь хотелось бы расположить иллюстрацию) Заключительный текст. Чтобы показать эту вкуснятину в окне браузера, разметим ее соответствующими тегами: <H1>Заголовок интересного текста</H1> <P> Первый абзац. В этом абзаце есть очень важное <EM>слово</EM>, которое выделено. </P> <P> Второй абзац. В нем приводится небольшая <CITE>цитата</CITE>, которая поддерживает изложение. </P> <P> <IMG src="pic/pic.jpg" alt="Интересная иллюстрация"> </P> Заключительный текст.
Внутри блочных элементов могут располагаться не только строчные, но и блочные элементы вперемежку со строчными: <DIV class=content> <STRONG>Выделенный текст</STRONG> <P>Первый абзац</P> <P>Второй абзац</P> Текст без разметки </DIV> Все строчные и неразмеченные элементы собираются в безымянные блоки: <DIV class=content> <БЛОК><STRONG>Выделенный текст</STRONG></БЛОК> <P>Первый абзац</P> <P>Второй абзац</P> <БЛОК>Текст без разметки</БЛОК> </DIV> Верстка выполняется прежним способом: блоки выводятся в прямоугольные области, следующие друг за другом сверху вниз.
Можно ли размещать внутри строчного элемента блочные? Стандарт языка (ссылка[2]) запрещает это (“строчные элементы могут содержать только данные и другие строчные элементы”), однако браузеры относятся к такой разметке довольно лояльно. Например, отображая следующий фрагмент кода, все браузеры выведут на экран жирный текст: <STRONG> <P>Текст внутри абзаца</P> </STRONG> Однако браузер Firefox код <CITE> Текст снаружи <P>Текст внутри абзаца</P> </CITE> преобразует в <CITE>Текст снаружи</CITE> <P>Текст внутри абзаца</P> (это можно увидеть в отладчике Firebug (ссылка[16])), и текст внутри абзаца не будет курсивным. В CSS есть свойство display, которое позволяет менять поведение элементов: значение block превращает элемент в блок, а значение inline — в строку. Так и происходит по поведению элемента на экране, но ни указание P {display:inline}, ни указание CITE {display:block} не помогают Firefox вывести курсивом текст внутри абзаца. И это соответствует стандарту.Стандарт утверждает: изменение ролей ничего не меняет, кроме характерного поведения на экране. Исходно строчные элементы могут быть потомками исходно блочных, но не наоборот. Нижеприведенные фрагменты одинаково неверны с точки зрения стандарта: <STRONG> <P style="display: inline">Текст внутри абзаца</P> </STRONG>
<CITE> Текст снаружи <P style="display: inline">Текст внутри абзаца</P> </CITE>
<CITE style="display: block"> Текст снаружи <P style="display: inline">Текст внутри абзаца</P> </CITE> Вывод: нужно следовать указаниям стандарта. Итак, элементы бывают блочные и строчные. Можно предложить еще одно деление на два класса. Оно пригодится при анализе алгоритмов работы браузера.
Например, абзац текста (P) является незамещаемым элементом, потому что его содержимое содержится в самом HTML-коде.
Например, элемент IMG является замещаемым элементом, потому что его код указывает на файл изображения, а само изображение в коде не присутствует. К замещаемым элементам относятся также элементы форм: обычные кнопки, радиокнопки, флажки, строки и поля для ввода текста. 1.2. Архитектура и поведение элемента1.2.1. Устройство блочного элемента
1.2.2. Схлопывание внешних отступов
1.2.3. Проваливание за границу родителя Расположим на странице три последовательных блока: <BODY> <DIV class="header"> <H1>Заголовок</H1> </DIV> <DIV class="text"> <P>Текст 1</P> </DIV> <DIV class="text"> <P>Текст 2</P> </DIV> </BODY>
1.2.4. Устройство строчного элемента Строчный элемент, как и блочный, имеет: содержимое, внутренний отступ (padding), границу (border) и внешний отступ (margin). Отступы слева и справа ведут себя как обычно, а вертикальные отступы имеют особенности. Пусть страница задана кодом: <BODY> <P> Выделенное <STRONG>слово</STRONG> внутри предложения. <P> Здесь <CITE>длинная цитата, которая переходит с одной строки на другую</CITE>. </BODY>
Таким образом, мы проверили на практике алгоритм форматирования строчных незамещаемых элементов:
Такое поведение мы обнаружим в процессе построения меню на вкладках (см. 1.6.3) и учтем его. Что касается замещаемых элементов, то они ведут себя иначе.
Пусть страница задана кодом: <BODY> <P> Выделенное <STRONG>слово</STRONG> внутри предложения. <P> Здесь <CITE>длинная цитата, которая переходит с одной строки на другую</CITE>. А здесь расположена <IMG src='pic/logo.png' border=0 hspace=0 vspace=0 alt=''> картинка. </BODY>
1.3. Размеры и выравнивание1.3.1. Строчные элементы
Свойства width и height никакого влияния на текстовый элемент не оказывают. С другой стороны, с помощью CSS можно менять параметры текста, и его размеры на экране будут меняться. · font-family — задает гарнитуру; · font-size — кегль; · font-style — начертание; · font-weight — плотность; · letter-spacing — расстояние между буквами; · line-height — расстояние между строчками. Размеры картинки определяются ее реальными размерами, но их можно задавать и атрибутами width, height элемента IMG или одноименными свойствами CSS. Для выравнивания строчных элементов по горизонтали применяется свойство text-align со значениями: left, right, center, justify. Это свойство должно быть задано в родительском блоке.
1.3.2. Блочные элементы Размеры блочного элемента определяют CSS-свойства width и height. Если размеры не заданы, то ширина блока совпадает с шириной родителя (вместе с границей и всеми отступами), а высота определяется по содержимому. Если горизонтальный размер блока меньше родительского, его можно выравнивать с помощью значения auto для внешнего отступа (margin) выравниваемого блока. Подробнее об интересном значении auto можно прочитать в следующем разделе. 1.3.3. Значение auto для размеров блока Рассмотрим алгоритмы работы свойства auto отдельно при горизонтальном и при вертикальном форматировании блока. 1.3.3.1. Горизонтальное форматирование
Горизонтальным форматированием блока можно управлять при помощи семи свойств, задающих размеры: · margin-left — внешний отступ слева; · border-left — рамка слева; · padding-left — внешний отступ слева; · width — ширина содержимого; · padding-right — внутренний отступ справа; · border-right — рамка справа; · margin-right — внешний отступ справа.
Алгоритмы работы этих свойств при значении auto основаны на общем правиле горизонтального форматирования потока.
Если одному из свойств margin-left, width или margin-right задано значение auto, а для остальных — определенные значения, то свойство, заданное как auto, определяет размер, необходимый для размещения блока по ширине родителя. Вот чем объясняется способ выравнивания блока слева и справа по отношению к родителю, когда он его меньше: Если оба отступа установлены в auto , для них устанавливается одинаковый размер, и блок центрируется:
Посмотрим теперь, как будут вычисляться размеры, если присвоить значение auto одному из отступов и ширине.
Если значение auto принимают все три свойства, то оба отступа обращаются в ноль, а ширина становится максимальной. Наконец, если всем трем свойствам заданы определенные значения, то свойству margin-right принудительно присваивается auto для языков с написанием слева направо. Для языков с написанием справа налево в auto устанавливается свойство margin-left. 1.3.3.2. Вертикальное форматирование Вертикальным форматированием блока можно управлять при помощи семи свойств, задающих размеры: · margin-top — внешний отступ сверху; · padding-bottom — внутренний отступ снизу; · border-top — рамка слева; · border-bottom — рамка снизу; · padding-top — внешний отступ слева; · margin-bottom — внешний отступ снизу. · height — высота содержимого;
Алгоритмы работы этих свойств при значении auto основаны на общем правиле вертикального форматирования потока.
Если для свойств margin-top или margin-bottom задано значение auto, им автоматически присваивается нулевое значение. Размер блока со значением height:auto определяется таким образом, чтобы его высоты как раз хватило для размещения содержимого. 1.4. Проблемы размеров и их решение1.4.1. Проблемы
Кроме того, заданы: · ширина 400 пикселей (width: 400px); · высота 200 пикселей (height: 200px). Возникает вопрос: к какому объекту относятся 400 и 200 пикселей?
Эта разница приводит к краху блочной разметки в устаревших (но еще популярных) версиях IE, если разработчик следовал стандартам.
Самый простой способ избежать обозначенной проблемы — не задавать внутренние отступы и границы для блока, если для него указаны ширина или высота. Отступы и границу можно задавать для родителя или потомков. Если такое решение невозможно, можно воспользоваться трюками, описанными ниже. 1.4.2. Решение Тантека Целика Решение проблемы описано Тантеком Целиком (Tantek Celik) — сотрудником компании Microsoft — в статье “Box Model Hack”. С русским переводом этой статьи можно ознакомиться на сайте Webmascon (ссылка[7] ) (статья “Трюк с блочной моделью CSS”, ссылка[11]). Тантек Целик предлагает следующий трюк: 1 .area 2 { 3 padding: 10px; 4 border: 5px solid black; 5 width: 430px; /* подделка для IE5 и IE6 Transitional */ 6 height: 230px; /* подделка для IE5 и IE6 Transitional */ 7 voice-family: "\"}\""; 8 voice-family:inherit; 9 width: 400px; /* размер содержимого по стандарту */ 10 height: 200px; /* размер содержимого по стандарту */ 11 } В строках 5 и 6 задаются ширина и высота блока для IE5 и IE6. Затем в строках 7 и 8 старые браузеры сбиваются с толку правилами CSS2, которые они не понимают. “Умные” браузеры продолжают чтение правил и доходят до строк 9 и 10, в которых указаны размеры по стандарту. Объясним подробнее, что происходит. IE5 и IE6 не понимают свойства voice-family, поэтому игнорируют его. Но когда они натыкаются на закрывающую фигурную скобку в строке 7, то воспринимают ее как конец всего определения area (это известный баг этих браузеров). То есть IE5 и IE6 не смогут прочитать строк 9 и 10, в которых указаны значения по стандарту. Браузеры, которые понимают свойство voice-family, видят, что ему назначено неизвестное значение, и полностью (вместе с “}”) игнорируют его. Чтобы люди, которые сайты не читают, а слушают, могли услышать и этот блок, в строке 8 задается свойство voice-family:inherit: оно указывает, что параметр голоса наследуется от родительского элемента. Возможно, трюк показался вам сложным, тогда просто запомните инструкцию, не вникая в ее подробности: · сначала указываем размер блока для IE5 и IE6 (оно равно размеру содержимого плюс суммарный размер внутренних отступов плюс суммарный размер границ); · потом записываем “магические” строки 7 и 8, чтобы остановить IE5 и IE6; · наконец, указываем размер блока по стандарту (совпадает с размером содержимого). С браузером Opera 7 возникает дополнительная проблема. Этот браузер обрабатывает размер блока по стандарту, понимает CSS2, но имеет тот же баг, связанный с разбором выражения "\"}\"", что и IE5, это не позволяет ему прочитать правильный размер в строках 9 и 10. Для преодоления этой сложности Тантек Целик предложил использовать дополнительное определение (специально для Opera 7): html>body .area /* Реверанс для Opera 7 */ { width: 400px; /* размер содержимого по стандарту */ height: 200px; /* размер содержимого по стандарту */ } Селектор “>” является селектором CSS2 (задает дочернюю зависимость). Этот селектор браузеры IE5 и IE6 не понимают, а Opera поддерживает с версии 5. 1.4.2.1. Пример построения блока Пусть требуется построить блок area, изображенный на рисунке. 1.4.2.1. Пример построения блока Пусть требуется построить блок area , изображенный на рисунке. Решением будет следующий набор CSS-определений: .area { margin: 15px; border: 5px solid #4d4d4d; padding: 20px; width: 450px; /* подделка для IE5 и IE6 Transitional */ height: 350px; /* подделка для IE5 и IE6 Transitional */ voice-family: "\"}\""; /* остановим IE5/6 (трюк Целика) */ voice-family:inherit; /* наследуем голос от родителя */ width: 400px; /* размер содержимого по стандарту */ height: 300px; /* размер содержимого по стандарту */ } html>body .area /* реверанс для Opera 7 */ { width: 400px; /* размер содержимого по стандарту */ height: 300px; /* размер содержимого по стандарту */ } 1.4.3. Упрощенные уловки Трюк Тантека Целика был самым первым решением описанной проблемы. Код этой уловки можно встретить во многих гипертекстовых проектах, и теперь мы знаем, что означают эти загадочные строки. Однако существуют и более простые решения. Опишем два из них. 1.4.3.1. Первая упрощенная уловка Вот она: .area { width: 400px; /* Для хороших старых браузеров */ \width: 450px; /* Обман для IE5 */ w\idth: 400px; /* Для всех новых хороших браузеров */ } Трюк основан на использовании символа “\” — обратной косой черты. Это допустимый символ, описанный в стандарте CSS. Он используется в качестве модификатора, меняющего специальный смысл следующего за ним знака на обычный. Рассмотрим пример. Приведенное ниже определение задает рамку для всех картинок, у которых атрибут alt имеет значение "Фото класса": IMG[alt="Фото класса"] { border: 1px solid black } Кавычки, окружающие строку, являются специальными символами языка. А что если кавычки нужны внутри строки? Вот здесь нам и поможет символ “\”: IMG[alt="Фото 5\"А\" класса"] { border: 1px solid black } Обратная косая черта отменяет специальный смысл кавычки, которая следует непосредственно за ней. А если у символа нет специального смысла? Значит, и отменять нечего, символ остается прежним. Использовать обратную косую черту можно не только в записи строки, но и в записи идентификатора. Таким образом, \width и w\idth полностью эквивалентны width. Какой же смысл в приведенном трюке? .area { width: 400px; /* Для хороших старых браузеров */ \width: 450px; /* Обман для IE5 */ w\idth: 400px; /* Для всех новых хороших браузеров */ } Первая строка уловки — для тех браузеров, которые работают по стандарту, но не понимают модификатора (к ним относится, например, браузер Opera 5). Эти браузеры будут рассматривать символ “\” как обычный знак, входящий в состав имени свойства, не “узнают” width и пропустят строки 2 и 3. Вторая строка — для браузера IE5, который работает не по стандарту, не считает обратную косую черту модификатором в середине слова, но, по счастью, считает этот знак модификатором, если с него слово начинается. Таким образом, IE5 (и IE6, если он работает в режиме IE5) сначала прочитает 400px в первой строке, потом изменит это значение на 450px из второй строки, а третью строку проигнорирует. Третья строка — для совсем хороших браузеров: тех, которые работают во всем по стандарту, в том числе правильно понимают символ обратной косой черты. Пример построения блока
Решением будет следующий набор CSS-определений: .area { margin: 15px; border: 5px solid #4d4d4d; padding: 20px; width: 400px; /* Для хороших старых браузеров по стандарту */ \width: 450px; /* Обман для IE5 */ w\idth: 400px; /* Для всех новых хороших браузеров по стандарту */ height: 400px; /* Для хороших старых браузеров по стандарту */ \height: 450px; /* Обман для IE5 */ he\ight: 400px; /* Для всех новых хороших браузеров по стандарту */ } Нельзя было записать h\eight по следующей причине. Знак “\” используется и для кодирования символов 16-ричными цифрами. Если за обратной косой чертой следует один из знаков 0-9, a, b, c, d, e, f, то это воспринимается как начало 16-ричного кода. Отметим заодно еще одну функцию обратной косой черты — обозначать продолжение записи на следующей строке: IMG[alt="Фото класса, которое было выполнено \ Петром Ивановичем Сидоровым, классным \ руководителем (во всех смыслах)"] { border: 1px solid black } 1.4.3.2. Вторая упрощенная уловка Вторая уловка представлена следующими правилами: .area { width: 400px; /* Для всех хороших браузеров */ }
* HTML .area /* Это правило понимают только IE */ { width: 450px; /* Обман для IE5 */ w\idth: 400px; /* Для хороших IE */ } По стандарту в корне иерархии элементов страницы расположен элемент HTML. Именно так строят объектную модель страницы все браузеры, кроме IE. Браузеры IE располагают в корне некий безымянный элемент, а HTML содержится в нем уже как потомок. Селектор * HTML .area определяет элементы с классом area, которые являются потомками элемента HTML, который, в свою очередь, является потомком какого-либо другого элемента (селектор *). Для любого браузера, кроме IE, селектор * HTML .area не указывает ни на один объект, так как нет элементов, у которых потомком был бы HTML. Таким образом, этот селектор сработает только для IE. Пример построения блока
Решением будет следующий набор CSS-определений: .area { margin: 15px; border: 5px solid #4d4d4d; padding: 20px; width: 400px; /* По стандарту */ height: 400px; /* По стандарту */ } * HTML .area /* Это правило понимают только IE */ { width: 450px; /* Обман для IE5 */ w\idth: 400px; /* Для хороших IE */ height: 450px; /* Обман для IE5 */ he\ight: 400px; /* Для хороших IE */ } Представительный набор CSS-уловок (с подробным описанием) собран в удобную таблицу на странице CSS-only Filters Summary (ссылка[12]). 1.5. Как работает браузер. Верстка потоком1.5.1. Дизайн кода и слепой браузер
В правильно сверстанном коде иерархическая лесенка подпирает теговый каркас на блочных элементах и почти не мешает читать содержание (строчные элементы), набранное по обычным правилам — ровный край слева и максимально ровный край справа: <BODY> <H1>Дизайн кода<H1> <!-- Первый раздел --> <P> В <EM>правильно сверстанном
коде</EM> иерархическая лесенка подпирает
теговый каркас на <EM>блочных элементах</EM>
и почти не мешает читать содержание (<EM>строчные
элементы </P> </BODY> Применяя двумерную верстку, разработчик старается не для браузера, а для тех, кто будет читать и править код, то есть для самого себя и своих коллег. Что касается браузера, он заменяет концы строк пробелами, а каждую группу пробелов — единственным пробелом. То есть браузер видит код в виде одной строки, игнорируя лишние пропуски, концы строк и комментарии: <BODY> <H1>Дизайн кода<H1> <P> В <EM>правильно сверстанном коде</EM> иерархическая лесенка подпирает теговый каркас на <EM>блочных элементах</EM> и почти не мешает читать содержание (<EM>строчные элементы</EM>), набранное по обычным правилам — ровный край слева и максимально ровный край справа. </P> </BODY> Перед браузером стоит задача отобразить одномерную строку кода на двумерную поверхность своего окна. Посмотрим, как браузер выполняет эту работу по умолчанию, то есть когда в его деятельность не вмешиваются позиционированные (см. 2) и плавающие (перемещаемые) (см. 3) элементы. Такая верстка называется потоком.
1.5.2. Верстка потоком
По умолчанию браузер выводит блочные элементы друг за другом сверху вниз. При этом ширина блочного элемента совпадает с доступной шириной родителя (его свойством width), а высота определяется по содержимому. Каждый раз, когда внутри блока обнаруживаются блочные элементы, они строятся на экране прямоугольниками сверху вниз по ширине родителя. Если в блоке есть смесь блочных и строчных элементов (на уровне прямых потомков), то все строчные элементы (а также неразмеченный текст) собираются в безымянные блоки и строятся по описанному выше алгоритму построения блоков.
Строки по умолчанию выравниваются со стороны, принятой для текущего языка (слева для русского). При изменении ширины окна браузер переверстывает страницу: ширину блоков подгоняет под новый размер, ширину строк — под изменившуюся ширину содержащих их блоков. В силу этого верстку потоком называют резиновой версткой. 1.6. Пример построения меню на вкладкахПостановка задачи: построить меню, изображенное на рисунке: Много говорилось о преимуществах CSS, о том, как этот механизм позволяет сократить код HTML, сделать его простым, логичным, полностью удалить из него визуальное наполнение, упростить будущие правки и тем не менее сохранить контент доступным для тех средств просмотра, которые не поддерживают CSS (старые браузеры, карманные компьютеры и мобильные телефоны). Построим меню на вкладках, используя верстку потоком. 1.6.1. HTML-код
Чтобы связать нашу HTML-конструкцию с определениями CSS, блоку-контейнеру UL присвоен класс menu. Мы будем по-другому отображать пункт, относящийся к текущей странице, вот почему он “обернут” в строчный элемент SPAN. Остальные пункты доступны по селектору .menu A, а этот — по селектору .menu SPAN. Наконец, первый элемент списка выделен классом first. Только для того, чтобы можно было задать для него внешний отступ слева. Конечно, можно было бы не заводить этот класс и получить доступ к первому потомку блока UL при помощи селектора .menu LI:first-child, но IE-6 не понимает этого указания. 1.6.2. Применим CSS Вначале сформулируем правила CSS, которые сделают список горизонтальным. Заодно добавим фоновую полоску и зададим свойства шрифта. .menu { margin:0; /* удалим списочный отступ */ list-style:none; /* запретим показывать маркер */ white-space:nowrap; /* запретим переносить строку */ background: #ffcd2d; /* фоновая полоска */ }
.menu LI { display:inline; /* превратим LI в строчный элемент */ font-family: Arial, sans-serif; font-size:70%; }
.menu LI.first /* отступ первого LI */ { margin-left:40px; } Вот что теперь мы увидим на экране (поток/меню на вкладках/шаг 2).
1.6.3. Придадим вкладкам форму .menu A, .menu SPAN /* правила для всех вкладок */ { border: 1px solid #9b8748; /* рамка */ padding:2px 6px; /* отступы */ color:#333; /* серый цвет шрифта */ background: #f9e9a9; /* фон вкладки */ text-decoration: none; /* уберем подчеркивание со ссылок */ }
.menu SPAN /* переопределения для вкладки текущей страницы */ { border-color: black; /* черный цвет для рамки */ background: white; /* белый цвет фона */ color:black; /* черный цвет для шрифта */ }
Получили такое изображение (поток/меню на вкладках/шаг 3). Может показаться странным, что вкладки вышли по вертикали за пределы содержащего их блока menu. Однако это не баг, а следование алгоритму построения строк в потоке, который мы обсуждали в разделе “Архитектура и поведение элемента” (см. 1.2.4). Вертикальные отступы и рамки строчных элементов не учитываются при вычислении высоты содержащего их контейнера. Для расширения фоновой полоски мы вынуждены указать отступы и для содержащего блока: .menu { margin:0; /* удалим списочный отступ */ list-style:none; /* запретим показывать маркер */ white-space:nowrap; /* запретим переносить строку */ background: #ffcd2d; /* фоновая полоска */ padding: 14px 0 2px 0px; /* расширение фоновой полоски */ } Получается гораздо лучше (поток/меню на вкладках/шаг 4). Теперь нужно провести черную линию снизу у общего фона, а также изменить цвет нижней рамки у всех вкладок: у всех A — на черный, а у вкладки SPAN — на белый. .menu { margin:0; /* удалим списочный отступ */ list-style:none; /* запретим показывать маркер*/ white-space:nowrap; /* запретим переносить строку*/ background: #ffcd2d; /* фоновая полоска */ padding: 14px 0 2px 0px; /* расширение фоновой полоски */ border-bottom: 1px solid black; /* черная рамка снизу */ } .menu A, .menu SPAN /* правила для всех вкладок */ { border: 1px solid #9b8748; /* рамка */ padding:2px 6px; /* отступы */ color:#333; /* серый цвет шрифта */ background: #f9e9a9; /* фон вкладки */ text-decoration: none; /* уберем подчеркивание ссылок */ border-bottom-color: black; /* черный цвет у рамки снизу */ } .menu SPAN /* переопределения для вкладки текущей страницы */ { border-color: black; /* черный цвет для рамки */ background: white; /* белый цвет фона */ color:black; /* черный цвет для шрифта */ border-bottom-color: white; /* белый цвет у рамки снизу */ } Получается практически готовый результат (поток/меню на вкладках/шаг 5).
Подключим созданные картинки при помощи следующих CSS-правил: .menu A, .menu SPAN /* правила для всех вкладок */ { border: 1px solid #9b8748; /* рамка */ padding:2px 6px; /* отступы */ color:#333; /* серый цвет шрифта */ text-decoration: none; /* уберем подчеркивание со ссылок */ border-bottom-color: black; /* черный цвет у рамки снизу */ background: #f9e9a9 url(pic/offkey.png) repeat-x top left; /* фон вкладки */ } .menu SPAN /* переопределения для вкладки текущей страницы */ { border-color: black; /* черный цвет для рамки */ color:black; /* черный цвет для шрифта */ border-bottom-color: white; /* белый цвет у рамки снизу */ background: white url(pic/onkey.png) repeat-x top left; /* фон вкладки */ } Вот как это выглядит в окне браузера (поток/меню на вкладках/шаг 6).
1.6.4. Динамические свойства ссылок Воспользуемся псевдоклассами, которые задают свойства ссылок: /* Динамические свойства ссылок */ .menu A:link {color:#333} /* цвет непосещенной ссылки */ .menu A:visited {color:purple} /* цвет посещенной ссылки */ .menu A:hover /* когда курсор над ссылкой */ { background: #ff7f00 url(pic/hoverkey.png) repeat-x top left; color:white; border-color: white; border-bottom-color: black; } .menu A:active {color:red} /* цвет активной ссылки */ Для события A:hover пришлось нарисовать еще одну фоновую картинку (hoverkey.png). Теперь, когда курсор над ссылкой, ссылка сигналит о своей готовности выполнить переход (поток/меню на вкладках/шаг 7 — работают переходы на страницу 1 и начало). Порядок, в котором идут определения стилей ссылок, важен. Он должен подчиняться правилу LVHA: A:link, A:visited, A:hover, A:active. Почему так? Потому что эти правила работают вместе и могут конфликтовать. При щелчке на непосещенной ссылке, например, последняя сопоставляется с тремя правилами — A:link, A:hover и A:active. Побеждает то правило, которое идет последним. Пусть, например, определения записаны в другом порядке: A:active { ... } A:hover { ... } A:link { ... } A:visited { ... } При таком расположении определений ни одна из ссылок никогда не продемонстрирует стили A:hover и A:active, потому что всегда будут побеждать правила A:link и A:visited, которые идут последними. 1.6.5. Подключаем JavaScript В самом начале раздела мы записали меню в виде: <UL class="menu"> <LI class=first><SPAN>начало</SPAN> <LI><A href="01.htm">страница 1</A> <LI><A href="02.htm">страница 2</A> <LI><A href="03.htm">страница 3</A> <LI><A href="04.htm">страница 4</A> </UL> Это меню — для главной страницы сайта. На странице 1 оно будет иметь вид: <UL class="menu"> <LI class=first><A href="index.htm">начало</A> <LI><SPAN>страница 1</SPAN> <LI><A href="02.htm">страница 2</A> <LI><A href="03.htm">страница 3</A> <LI><A href="04.htm">страница 4</A> </UL> Аналогично меню записываются и для других страниц сайта: для текущей страницы элемент A заменяется элементом SPAN. Несложно, но… все же придется повозиться с каждой страницей, утешаясь тем, что эта работа выполняется один раз. Стоп! А если в готовый сайт заказчик задумает добавить новую страницу? Или изменить название существующей? Вот это настоящая проблема: придется выполнять правки на всех страницах сайта. Ужасно! Мы поместили визуальное представление объекта в отдельный файл и гордо заявляем, что для правки внешнего вида придется править только один этот файл CSS, а не сотни файлов HTML. Какой казус! Но решение есть. Пустим в ход моторчик JavaScript: напишем функцию putmenu. У этой функции будет один параметр — номер текущей страницы. Тогда меню на начальной странице будет задаваться так: <!-- Меню --> <SCRIPT language="JavaScript" type="text/javascript"> <!-- putMenu(0); //--> </SCRIPT> На странице 1 так: <!-- Меню --> <SCRIPT language="JavaScript" type="text/javascript"> <!-- putMenu(1); //--> </SCRIPT> И так далее. Определение функции поместим в отдельный файл JS, а в головной части каждого HTML поставим ссылку на этот файл (main.js). Заметим, что ссылка на файл со стилями (main.css) давно уже присутствовала: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML lang="ru"> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=windows-1251"> <META http-equiv="author" content="А. А. Дуванов"> <META http-equiv="Content-Style-Type" content="text/css"> <!--LINK rel="stylesheet" type="text/css" href="main.css" --> <STYLE type="text/css">@import url(main.css);</STYLE> <SCRIPT language="JavaScript" type="text/javascript" src="main.js"></SCRIPT> <TITLE>Заголовок окна</TITLE> </HEAD> <BODY> <H1>Заголовок сайта</H1> <!-- Меню --> <SCRIPT language="JavaScript" type="text/javascript"> <!-- putMenu(0); //--> </SCRIPT> <H2>Заголовок страницы</H2> <P>Содержание</P> </BODY> </HTML>
1.6.5.1. Разработка функции putmenu Создаем пустой файл main.js и начинаем работу. Прежде всего опишем данные. // Пункты меню // ----------- var ItemsMenu = new Array ( new Array ("начало", "index.htm"), new Array ("страница 1", "01.htm"), new Array ("страница 2", "02.htm"), new Array ("страница 3", "03.htm"), new Array ("страница 4", "04.htm"), new Array ("ссылки", "links.htm") ); // Константы // --------- var classMenu = "menu"; // Имя CSS-класса меню var classFirstLi = "first"; // Имя CSS-класса первого элемента списка Пункты меню размещаются в двумерном массиве ItemsMenu: · ItemsMenu[i][0] — название i-го пункта; · ItemsMenu[i][1] — имя файла для i-го пункта. А теперь код самой функции: // Построение меню // --------------- // Функция строит меню вида (в <SPAN> обертывается текущая страница): // <UL class="menu"> // <LI class=first><SPAN>начало</SPAN> // <LI><A href="01.htm">страница 1</A> // <LI><A href="02.htm">страница 2</A> // ... // </UL> function putMenu(page) // page -- номер текущей страницы в ItemsMenu { var str = '<UL class="'+ classMenu + '">'; for (var i = 0; i<ItemsMenu.length; i++) { str += '<LI' + (i ? '' : (' class="' + classFirstLi + '"')) + '>'; if (i == page) str += '<SPAN>' + ItemsMenu[i][0] + '</SPAN></LI>'; else str += '<A href="' + ItemsMenu[i][1] + '">' + ItemsMenu[i][0] + '</A></LI>'; } str += '</UL>'; document.write(str); } Функция формирует HTML-код в строке str и выводит его в окно браузера с помощью метода document.write. Посмотрим результат (поток/меню на вкладках/шаг 8 — работают переходы на все страницы). Замечаем, что исчезли промежутки между вкладками. Эти промежутки были благодаря концам строк в записи списка UL. Как известно, браузер воспринимает конец строки как пробел, поэтому расстояние между вкладками было равно ширине пробела текущего шрифта. HTML-код на JavaScript мы формировали плотно, без всяких пробелов, вот промежутки и пропали. Ура, если с самого начала вам казалось, что промежутков и не должно быть. Если же, напротив, они кажутся необходимыми, то их легко восстановить, добавив нужное указание в стилевые свойства: .menu LI { display:inline; /* превратим LI в строчный элемент */ font-family: Arial, sans-serif; font-size:70%; margin-left:0.5em; } 1.6.6. Что мы получили Мы создали один файл CSS, в который вынесли весь визуальный образ объекта. Мы создали один файл JavaScript, в котором расположили формирование HTML-кода объекта в зависимости от номера страницы. Мы создали много файлов HTML, в которых объект строится при помощи функции на JavaScript. В итоге возникли следующие преимущества. · Мы отделили структуру объекта от его визуального образа, полностью перенеся последний в CSS-файл. · HTML-код объекта получился предельно простым и коротким. Он отражает только структуру и не содержит никакого визуального мусора (картинок, таблиц). · Небольшой HTML-код объекта был еще сокращен до вызова единственной функции putmenu на JavaScript. · Правда, появились два новых файла, CSS и JavaScript, но они будут кэшироваться браузером и загружаться только один раз. Таким образом, мы сократили время загрузки страниц сайта. · Кроме того, мы облегчили себе работу по редактированию сайта. Если нужно поменять визуальный образ объекта, мы будем работать с единственным файлом CSS, а не с сотнями файлов HTML. Если нужно поменять содержание объекта, мы будем работать с единственным файлом JavaScript, а не с сотнями файлов HTML. · В построенном меню хорошо видны посещенные ссылки — они отображаются пурпурным цветом. Значит, пользователь не будет дважды щелкать по одной ссылке, просматривая страницы сайта. · Попробуйте увеличить или уменьшить размер шрифта в браузере. Наше меню автоматически масштабируется, радуя глаза пользователя. Попробуйте менять ширину окна — меню снова устояло, оно не разваливается на куски, не превращается в кашу. · Попробуйте посмотреть на наше меню в браузере без CSS. Оно имеет понятный вид списка и работает, как ни в чем не бывало. Ах, какие же мы молодцы! Тема 2. Позиционирование
Значение static размещает элемент на странице так, как он располагался бы без всякого позиционирования, поэтому использование этого значения не дает ничего нового. Остальные виды позиционирования рассмотрены в соответствующих разделах. Содержание темы2.1. Абсолютное позиционирование (absolute) 2.2. Фиксированное позиционирование (fixed) 2.3. Относительное позиционирование (relative) 2.4. Пример (построение сайта “Роботландия”) 2.5. Продолжение 1 2.6. Продолжение 2 2.1. Абсолютное позиционированиеСначала рассмотрим абсолютное позиционирование блочных элементов, а затем уточним приведенные алгоритмы для строчных элементов. 2.1.1. Позиционирование блочных элементов
Возникает важный вопрос: относительно чего указываются смещения для абсолютно позиционированного блока? Простой ответ “относительно родительского блока” оказывается верным, если для родителя также задано позиционирование (любое, кроме static). Если это не так, то смещения откладываются от “дедушки”, то есть от родителя родителя. Если “дедушка” не позиционирован, то от его родителя. И так далее до корня иерархии, то есть до HTML. Таким образом, браузер поднимается вверх по иерархической цепочке, пока не обнаружит позиционированный блок. Если такого блока нет, смещения отсчитываются от HTML.
Ранее был рассмотрен пример, в котором для абсолютно позиционированного блока одновременно задавались противоположные смещения (left:0 и right:0). К сожалению, одновременное указание противоположных смещений не работает в браузере IE (он выполняет left:0, но игнорирует right:0). Подробнее об этом в следующем разделе. 2.1.2. Проблема противоположных смещений Рассмотрим пример, в котором для абсолютно позиционированного блока одновременно задаются противоположные смещения (left:0 и right:0).
К сожалению, одновременное указание противоположных смещений не работает в браузере IE (он выполняет left:0, но игнорирует right:0). Для IE можно написать отдельную строку, в которой нужная ширина блока будет вычисляться при помощи выражения на JavaScript: /* Это работает во всех современных браузерах */ #block2 { position:absolute; top:120px; left:0; right:0; /* IE это указание игнорирует, поэтому специально для него указываем ширину блока выражением на JavaScript: */ width: expression(this.parentNode.offsetWidth-22); background:#fff2a6; } Для свойства width указано значение функции expression от выражения на JavaScript. Здесь: · this — текущий блок; · this.parentNode — родитель текущего блока; · this.parentNode.offsetWidth — ширина родителя; · 22 — сумма padding'ов и border'ов с двух сторон текущего блока. Показанный прием обеспечивает правильную работу во всех браузерах. Все, кроме IE, правильно отработают right:0 и пропустят expression, так как не понимают этой функции. IE, наоборот, пропустит right:0 (или left:0 для языков с написанием справа налево), зато выполнит expression.
2.1.3. Позиционирование строчных элементов Если строчный элемент абсолютно позиционируется, то он автоматически переводится в элемент уровня блока. В остальном отличий нет. Пусть HTML-код записан в следующем виде: <BODY> <H1>Абсолютное позиционирование</H1> <P> В этом абзаце есть <STRONG>выделенный фрагмент текста</STRONG>. Для этого фрагмента задано абсолютное позиционирование. </P> </BODY>
2.1.4. Значение auto При абсолютном позиционировании значения auto для всех смещений, кроме bottom, означают такие величины, какие были бы у элемента, если бы он находился в потоке. Тот же эффект возникает, когда смещение не задается вовсе. Рассмотрим этот вопрос подробнее. Пусть HTML-код записан в следующем виде: <BODY> <H1>Значение auto</H1> <P> В этом абзаце есть выделенное <STRONG>слово</STRONG><SPAN>*</SPAN>. За этим словом следит маркер в виде красной звездочки. </P> </BODY>
Если для свойств left, width и right задать значение auto, то левый край помещается в его статическое положение (правый край для языков с написанием справа налево), ширина определяется по содержимому, а противоположное смещение вычисляется так, чтобы достичь границы блока, по отношению к которому элемент позиционируется. Если для свойств top, height и bottom задать значение auto, то верхний край помещается в его статическое положение, высота определяется по содержимому, а противоположное смещение вычисляется так, чтобы достичь границы блока, по отношению к которому элемент позиционируется. 2.2. Фиксированное позиционированиеЗначение fixed, как и absolute, задает элементу на экране абсолютные координаты. При этом смещения отсчитываются от границ области просмотра (viewport). То есть при прокрутке элемент сохраняет свое положение в окне. На базе значения fixed можно построить, например, навигационное меню, которое всегда остается под рукой пользователя. Запишем соответствующий код HTML: <BODY> <!-- Меню, которое не должно скролироваться --> <DIV class="menu"> <UL> <LI>пункт 1 <LI>пункт 2 <LI>пункт 3 <LI>пункт 4 <LI>пункт 5 </UL> </DIV> <DIV class="content"> Длинное содержание страницы </DIV> </BODY>
Сделаем два важных для практики замечания.
К сожалению, фиксированное позиционирование не поддерживают браузеры IE вплоть до версии IE7 (здесь поддержка включена). Рассмотрим возможные способы моделирования фиксированного позиционирования при помощи абсолютного. 2.2.1. Вариант 1
2.2.2. Вариант 2 Рассмотрим еще один способ, в котором фиксированное позиционирование задается для всех браузеров, а для IE моделируется абсолютным при помощи JavaScript. Стилевые правила зададим следующим образом: BODY { margin:0; padding:0; /* Зафиксируем фон, чтобы не было дрожаний */ background: url(empty.gif) no-repeat; background-attachment: fixed; } .menu { width:150px; top:10px; left:10px; border: 1px solid black; background:#fff2a6; /* Для хороших браузеров */ position:fixed; /* Для IE */ //position: absolute; top: expression(eval(document.body.scrollTop ? (document.body.scrollTop+10) : (document.documentElement.scrollTop+10))+"px"); } .content { margin: 10px 10px 10px 170px; padding:10px; border: 1px solid black; background:#a7fbc0; } Строка с expression выглядит немного жутковато, но в ней нет ничего сложного, как мы увидим. Давайте разбираться по порядку. В определении для content ничего не изменилось. Для BODY задан фиктивный фоновый рисунок empty.gif (такого файла нет в каталоге) и задано свойство background-attachment: fixed, обеспечивающее неподвижность фона при скролировании. Все это сделано, чтобы избежать дрожания меню при скролировании окна в IE. Эта уловка описана в Техногрете (ссылка[8]) студии Лебедева в статье Андрея Шитова “Полноценный fixed в MSIE”. Наконец, подойдем к самому главному — к описанию свойств menu. Начало вполне добропорядочно, оно устанавливает position:fixed для “хороших” браузеров и задает смещения блока (top и left ): .menu { width:150px; top:10px; left:10px; border: 1px solid black; background:#fff2a6; /* Для хороших браузеров */ position:fixed; ... } Следующая строка переустанавливает свойство position в absolute для браузеров IE: .menu { width:150px; top:10px; left:10px; border: 1px solid black; background:#fff2a6; /* Для хороших браузеров */ position:fixed; /* Для IE */ //position: absolute; top: expression(eval(document.body.scrollTop ? (document.body.scrollTop+10) : (document.documentElement.scrollTop+10))+"px"); } Еще одна особенность IE. Если поставить перед свойством две наклонные черты (//), оно будет восприниматься лишь IE (всех версий). Другие браузеры такое свойство проигнорируют. Вот и добрались до последней строки. В ней значение для top вычисляется функцией expression, содержащей выражение на JavaScript. Как уже отмечалось в разделе “2.1.2. Проблема противоположных смещений”, функцию expression понимают только браузеры IE. Что же делает функция expression? Она вычисляет вертикальную координату области просмотра относительно начала документа. Эту координату содержит свойство scrollTop прокручиваемого объекта. В старых IE таким объектом является document.body , в новых — document.documentElement . Таким образом, для старых IE нужно записать: top: expression(document.body.scrollTop); Для новых: top: expression(document.documentElement.scrollTop); Чтобы попасть в оба случая, применим условный оператор, который на JavaScript имеет такую форму: условие ? выражение1 : выражение2 Работает это так. Проверяется условие. Если оно верное, вычисляется выражение1, иначе выражение2. В нашем случае в качестве условия записано document.body.scrollTop: document.body.scrollTop ? выражение1 : выражение2 Если скролл относится к объекту document.body, то при вертикальной прокрутке значение document.body.scrollTop будет отлично от нуля, и условие станет справедливым. Теперь понятно, что надо записать в качестве первого и второго выражений: document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop Чтобы опустить меню вниз от края окна, добавим 10 к вычисляемым значениям: document.body.scrollTop ? (document.body.scrollTop+10) : (document.documentElement.scrollTop+10) Наконец, добавим к результату строку "px", как это требует CSS: eval(document.body.scrollTop ? (document.body.scrollTop+10) : (document.documentElement.scrollTop+10))+"px" Вот так это выглядит в браузере (позиционирование/фиксированное меню/вариант 2). Если в HTML убрать указание DOCTYPE, то новые IE переключатся в режим совместимости со старыми браузерами, и можно проверить работу кода и в них. 2.3. Относительное позиционирование Относительное позиционирование задается указанием position: relative. 2.3.1. Как это работает Если для такого элемента не заданы смещения (при помощи указаний left, right, top, bottom), он ведет себя как статический: остается в потоке и форматируется так, будто позиционирование для него не задано вовсе. Именно в таком качестве относительное позиционирование применяется чаще всего (без указания смещений). Рассматривая абсолютное позиционирование (см. 2.1.1), мы уже видели, зачем это нужно: таким образом указывается блок-предок, относительно которого отсчитываются смещения для абсолютно позиционированного элемента.
Если для относительно позиционированного элемента задаются смещения, они отсчитываются от его собственного положения в потоке. Элемент смещается, но его прежнее положение другие элементы не занимают. В качестве примера запишем такой HTML-код: <BODY> <H1>Занимательная история</H1> <P>Первый абзац. <P class=pos>Второй абзац. <P>Третий абзац. </BODY>
Получается, что относительно позиционированный элемент ведет себя как двуликий Янус! С одной стороны, он остается в потоке (даже если смещается), а с другой — располагается над ним. При изменении размеров окна или шрифта элемент с position: relative ведет себя так, будто находится в потоке. Он переформатируется вместе с потоком, а затем смещается. Продемонстрируем это поведение на следующем примере: <BODY> <H1>Строчный элемент</H1> <P> В этом абзаце задан <STRONG>относительно позиционированный строчный элемент</STRONG> STRONG. </BODY>
2.3.2. Противоположные смещения Что произойдет, если относительно позиционированному элементу задать противоположные смещения? Например, такие: P.pos { position: relative; left: 100px; right: 60px; } Элемент должен сместиться одновременно на 100 пикселей вправо (left: 100px) и на 60 пикселей влево (right: 60px ). Стандарт CSS2.1 (ссылка[1]) утверждает, что в этом случае одному из смещений присваивается значение, противоположное другому, основному. В качестве основных называются смещения left и top (right > и top для языков с написанием справа налево). Таким образом, для русского языка приведенное выше определение эквивалентно следующему: P.pos { position: relative; left: 100px; right: -100px; } Или такому: P.pos { position: relative; left: 100px; }
2.4. Пример (построение сайта “Роботландия”)
2.4.1. Обсуждение макета Макет представлен на рисунке.
Мы можем блокам header, sidebar и content назначить абсолютное позиционирование, если зафиксировать высоту блока header. Но как быть с подвалом? Высоты блоков sidebar и content будут меняться в зависимости от наполнения колонок. Значит, мы не знаем top для блока footer. Смещение bottom:0 вообще для него не годится — поток пуст, значит, низ блока footer поднимется (под вырванными из потока блоками) и склеится с верхом документа: footer вылезет вверх за пределы окна. (Если это рассуждение показалось вам неочевидным, остановитесь и подумайте, прежде чем двигаться далее.) На самом деле высоту header тоже не хочется фиксировать — пусть она гибко меняется под размер шрифта, если того пожелает пользователь.
Примем такое решение: все блоки, кроме sidebar, оставим в потоке. Для блока content зададим широкий внешний отступ слева и в освободившееся пространство поместим блок sidebar. 2.4.2. HTML-код
С небольшим наполнением: <BODY> <!-- Заголовочная часть --> <DIV id="header"> <H1>Роботландия</H1> </DIV> <!-- Конец header --> <!-- Боковая панель --> <DIV id="sidebar"> <H2>Содержание</H2> <UL> <LI>Начало <LI><A href="01.htm">Продукты</A> <LI><A href="02.htm">Университет</A> <LI><A href="03.htm">Ссылки</A> <LI><A href="04.htm">Автор</A> </UL> <H2>Новости</H2> <H3>31.01.09</H3> <P>Роботландии исполнилось 18 лет!</P> </DIV> <!-- Конец sidebar --> <!-- Содержание --> <DIV id="content"> <H2>О Роботландии</H2> <P> Курс с таким названием вошел в историю школьной информатики как образец комплексного педагогического продукта, удачно соединяющего в себе идейный фундамент, учебник для школьника, программное обеспечение и рекомендации для учителя. </P> </DIV> <!-- Конец content --> <!-- Подвал --> <DIV id="footer"> </DIV> <!-- Конец footer --> </BODY> 2.4.3. Без CSS
СсылкиОфициальные документы · CSS2.1 www.w3.org/TR/2007/CR-CSS21-20070719 Описание стандарта от W3C. · HTML 4.01 Описание стандарта от W3C. · Блочные элементы www.htmlhelp.com/reference/html40/block.html Полный список блочных элементов. · Строчные элементы www.htmlhelp.com/reference/html40/inline.html Полный список строчных элементов. Учебники · Учебник Ивана Сагалаева http://softwaremaniacs.org/blog/category/web/primer/ Лучшее из того, что можно назвать “учебником” по CSS-верстке. По крайней мере из того, что мне попадалось в Сети. Заметки по CSS, представленные на текущих страницах, написаны под впечатлением учебника Сагалаева. Справочники · Свойства CSS Справочник Влада Мержевича. Сборники статей · Webmascon “Здравствуйте, меня зовут Александр Качанов. Я — владелец и руководитель проекта Webmascon (ISSN: 1810-9527). Цель проекта — донести русскоязычному населению Интернета информацию по веб-дизайну, которая доступна только на английском языке. Более глобальная цель — пропаганда качественного, чистого, культурного и стандартного веб-дизайна”. · Техногрет www.artlebedev.ru/tools/technogrette На этих страницах технологи студии Артемия Лебедева делятся своими знаниями. · Статьи Статьи на сайте Влада Мержевича. Форумы · Форум Web http://softwaremaniacs.org/forum/web/866 Форум Ивана Сагалаева. Частные решения · Трюк с блочной моделью CSS www.webmascon.com/topics/coding/38a.asp Трюк Тантека Целика. · CSS-only Filters Summary. http://dithered.chadlindstrom.ca/css_filters/css_only/index.php Представительный набор CSS-уловок (с подробным описанием) в виде удобной таблицы. · Ложные колонки http://alistapart.com/articles/fauxcolumns Решение Дэна Седерхольма для колонок фиксированной ширины. · Ложные колонки (Дуглас Бауман) http://stopdesign.com/archive/2004/09/03/liquid-bleach.html Ложные колонки (Эрик Мейер) http://meyerweb.com/eric/thoughts/2004/09/03/sliding-faux-columns/ Решение для колонок процентной ширины. Разное · Lorem Ipsum www.lorem-ipsum.info/generator3 Lorem Ipsum генератор на разных языках (в том числе и на русском). · Firebug Отладчик Firebug. · Роботландия Сайт Роботландии.
А.. А.. Дуванов,
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||