Глава 1.7. Фреймы

1.7.1. Общее описание

Язык HTML позволяет авторам разбить окно обозревателя на несколько независимых подокон (называемых фреймами) так, что содержимое одних окон остается постоянным при прокрутке или изменении содержимого остальных окон. Например, окно обозревателя может быть разбито на три фрейма так: в верхней части отображается статический заголовок, слева — узкая полоса меню, а в остальной части окна отображается содержимое документов, выбранных во фрейме меню. Рассмотрим следующий пример:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
<HTML lang="ru">
<HEAD>
<TITLE>Пример фреймового документа</TITLE>
</HEAD>
<FRAMESET cols="20%, 80%">
  <FRAMESET rows="100, 200">
    <FRAME src="frame1.html">
    <FRAME src="frame2.gif">
  </FRAMESET>
  <FRAME src="frame3.html">
  <NOFRAMES>
    <P>Этот документ содержит:</P>
    <UL>
      <LI><A href="frame1.html">Первый документ</A></LI>
      <LI><IMG src="frame2.gif" alt="Изображение"></LI>
      <LI><A href="frame3.html">Второй документ</A></LI>
    </UL>
  </NOFRAMES>
</FRAMESET>
</HTML> 

Этот документ будет отображаться обозревателем примерно так:

Пример отображения фреймов

Из этого примера видно, что фреймовый документ:

  1. имеет особую декларацию типа документа (см. первую строку примера);
  2. вместо тегов <BODY>…</BODY> его тело заключается в теги <FRAMESET>…</FRAMESET>;
  3. может содержать элемент NOFRAMES, содержимого которого должно отображаться, если обозреватель не поддерживает фреймы.

1.7.2. Тело фреймового документа: элемент FRAMESET

Синтаксис: <FRAMESET>…</FRAMESET> (блочный элемент)
Атрибуты:  id, class, style, title
           rows = кратные размеры (размеры строк)
           cols = кратные размеры (размеры столбцов)
           onload = сценарий (документ загружен)
           onunload = сценарий (документ выгружен)
Поддержка: Internet Explorer Соответствует стандарту (5.0+)
           Netscape Navigator Соответствует стандарту (4.0+)

Тело фреймового документа описывает разбиение окна обозревателя на фреймы. Элемент FRAMESET употребляется вместо элемента BODY и должен располагаться сразу после заголовка документа. Он состоит из одного или нескольких элементов FRAMESET или FRAME, а также может содержать элемент NOFRAMES. Последний задает альтернативное содержание документа для обозревателей, не поддерживающих фреймы и не является обязательным. Тем не менее мы рекомендуем всегда включать его во фреймовый документ, причем его содержимым, как минимум, должна быть гиперссылка на главный фрейм (или фреймы).

Атрибуты rows и cols определяют размерность каждого из фреймов. Значением каждого из них является список кратных размеров, разделенных запятыми. Значения атрибута rows задают высоту каждой строки сверху вниз. Значения атрибута cols задают ширину каждого столбца слева направо. Если один из этих атрибутов опущен, то его значение по умолчанию 100%. Если оба атрибута указаны, то сетка фреймов заполняется слева направо, а потом сверху вниз.

Теперь мы можем пояснить приведенный выше пример. Первый элемент FRAMESET задает разбиение окна на два фрейма по вертикали, шириной 20% и 80% соответственно. Вложенный в него элемент FRAMESET задает дальнейшее разбиение первого фрейма на два фрейма по горизонтали, высотой 100 и 200 пикселей соответственно. В итоге мы получаем разбиение окна на три фрейма, как показано выше.

Кроме того, данный элемент поддерживает обработку двух нестандартных событий:

  • onload — происходит, когда обозреватель завершил загрузку всех фреймов документа;
  • onunload — происходит, когда обозреватель завершил выгрузку всех фреймов документа.

1.7.3. Описание фрейма: элемент FRAME

Синтаксис: <FRAME> (содержимого и конечного тега нет)
Атрибуты:  id, class, style, title
           name = CDATA (имя фрейма)
           src = URI (URI документа)
           longdesc = URI (URI подробного описания документа)
           frameborder = 1 | 0 (наличие рамки)
           marginwidth = пиксели (ширина полей)
           marginheight = пиксели (высота полей)
           noresize = noresize (запрет изменения размера фрейма)
           scrolling = yes | no | auto (полосы прокрутки фрейма)
Поддержка: Internet Explorer Атрибут longdesc игнорируется (5.0+)
           Netscape Navigator Атрибут longdesc игнорируется (4.0+)

Элемент FRAME определяет фрейм, т. е. прямоугольную область окна обозревателя, внутри элемента FRAMESET, который определяет размеры фрейма. Он может иметь следующие атрибуты:

  • Атрибут name задает имя фрейма, на которое может ссылаться атрибут target элементов A, AREA, BASE, FORM и LINK.
  • Атрибут src задает URI HTML-документа или иного ресурса, который должен отображаться в данном фрейме.
  • Атрибут longdesc содержит ссылку на подробное описание содержимого фрейма. Он должен дополнять краткое описание, содержащееся в атрибуте title, и особенно полезен, если содержимым фрейма является не документ, а графический образ, видеофайл или иной объект такого рода.
  • Атрибут frameborder указывает, должен ли быть фрейм заключен в рамку. По умолчанию он равен 1, т. е. рамка отображается; для отказа от ее отображения этому атрибуту следует присвоить значение 0. Заметим, что отмена рамки в большинстве обозревателей приводит к тому, что пользователь не может изменить размеры этого фрейма.
  • Атрибуты marginwidth и marginheight задают соответственно ширину и высоту пробельного поля, окружающего фрейм. Их значения задаются в пикселях и должны быть больше нуля.
  • Атрибут noresize запрещает пользователю изменять размеры фрейма, что крайне нежелательно без особых на то причин.
  • Атрибут scrolling определяет наличие у окна фрейма полос прокрутки. Он может принимать следующие значения:
Таблица 1.6. Полосы прокрутки окна фрейма
auto Полосы прокрутки создаются только при необходимости прокрутки окна фрейма для просмотра всего его содержимого (принято по умолчанию).
yes Полосы прокрутки создаются всегда, даже если они не нужны.
no Полосы прокрутки не создаются никогда, даже если нужны для просмотра всего содержимого фрейма. Никогда не пользуйтесь этим вариантом!

1.7.4. Альтернативное содержание: элемент NOFRAMES

Синтаксис: <NOFRAMES>…</NOFRAMES> (блочный элемент)
Атрибуты:  id, class, style, title, lang, dir, события
Поддержка: Internet Explorer Все атрибуты, кроме id, игнорируются (4.0+)
           Netscape Navigator Все атрибуты игнорируются (4.0+)

Элемент NOFRAMES задает альтернативное содержание фреймового документа для обозревателей, не поддерживающих фреймы. Он должен располагаться в конце тела документа, перед конечным тегом </FRAMESET> и может содержать любые элементы, которые допустимы внутри элемента BODY. Но по своему смыслу элемент NOFRAMES должен содержать гиперссылки на те документы и иные объекты, которые перечислены в элементах FRAME фреймовой части документа. Он не должен содержать рекомендации пользователю заменить или обновить обозреватель, т. к. многие обозреватели, даже поддерживающие фреймы, позволяют пользователю отключить их отображение.

1.7.5. Вложенный фрейм: элемент IFRAME

Синтаксис: <IFRAME>…</IFRAME> (текстовый элемент)
Атрибуты:  id, class, style, title
           name = CDATA (имя фрейма)
           src = URI (URI документа)
           longdesc = URI (URI подробного описания документа)
           align = top | middle | bottom | left | right (выравнивание фрейма)
           width = размер (ширина фрейма)
           height = размер (высота фрейма)
           frameborder = 1 | 0 (наличие рамки)
           marginwidth = пиксели (ширина полей)
           marginheight = пиксели (высота полей)
           scrolling = yes | no | auto (полосы прокрутки фрейма)
Поддержка: Internet Explorer Атрибут longdesc игнорируется (5.0+)
           Netscape Navigator Не поддерживается

Элемент IFRAME (inline frame) определяет вложенный фрейм, т. е. прямоугольную область окна обозревателя для отображения другого HTML-документа или иного объекта. По сравнению с элементом OBJECT он имеет меньше возможностей; единственным его преимуществом является то, что имя его фрейма может служить целью для последующих ссылок.

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

  • Атрибут name задает имя фрейма, на которое может ссылаться атрибут target элементов A, AREA, BASE, FORM и LINK.
  • Атрибут src задает URI HTML-документа или иного ресурса, который должен отображаться в данном фрейме.
  • Атрибут longdesc содержит ссылку на подробное описание содержимого фрейма. Он должен дополнять краткое описание, содержащееся в атрибуте title, и особенно полезен, если содержимым фрейма является не документ, а графический образ, видеофайл или иной объект такого рода.
  • Атрибуты width и height задают размеры фрейма на экране по горизонтали и вертикали соответственно.
  • Атрибут align задает выравнивание фрейма относительно содержимого вмещающего его элемента. Он может принимать следующие значения:
top вертикальное выравнивание по верхней части контекста
middle вертикальное выравнивание по центру контекста
bottom вертикальное выравнивание по нижней части контекста
left выравнивание по левому полю; содержание обтекает фрейм справа
right выравнивание по правому полю; содержание обтекает фрейм слева

Примечание. Свойства таблиц стилей vertical-align и float обеспечивают более гибкую настройку выравнивания фрейма.

  • Атрибут frameborder указывает, должен ли быть фрейм заключен в рамку. По умолчанию он равен 1, т. е. рамка отображается; для отказа от ее отображения этому атрибуту следует присвоить значение 0.
  • Атрибуты marginwidth и marginheight задают соответственно ширину и высоту пробельного поля, окружающего фрейм. Их значения задаются в пикселях и должны быть больше нуля.
  • Атрибут scrolling определяет наличие у окна фрейма полос прокрутки. Его возможные значения перечислены в Таблице 1.6.

Примечание. Элемент IFRAME не имеет атрибута noresize, так как размеры вложенного фрейма никогда не могут быть изменены.

1.7.6. Дискуссия о фреймах — за и против

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

1.7.6.1. Идеологические доводы противников фреймов

Суть WWW как распределенной гипертекстовой информационной системы состояла во введении понятия Веб-страницы. Страница (она же HTML-документ) — это атомарная составляющая WWW, которая одновременно представляет собой:

  • единицу отображаемой информации, видимую на экране обозревателя;
  • навигационную единицу, которая загружается при щелчке на гиперссылке или при выборе закладки в "Избранном";
  • единый текстовый адрес (URI) соответствующего ресурса;
  • единицу информации, хранимой на сервере и подлежащей авторской правке и сопровождению (один текстовый файл).

Фреймы разрушают это внутреннее единство Веб-архитектуры. Фреймовая Веб-страница состоит из нескольких HTML-документов, а это значит, что единица отображаемой информации теперь не совпадает ни с одной из единиц хранения информации и не является навигационной единицей (для получения на экране желаемого результата пользователь должен произвести серию переходов по гиперссылкам). Более того, URI перестают быть унифицированными идентификаторами страниц: если мы просто скопируем URI фреймовой страницы из адресного поля обозревателя и поместим его как адрес ссылки на свою страницу или в "Избранное", то после перехода по этой ссылке мы увидим не то, что нам бы хотелось, а начальное отображение фреймового документа. Иными словами, некоторые Веб-страницы оказываются лишенными собственного адреса, что противоречит само сущности WWW.

Фреймы противоречат и основной концепции языка HTML — каждый элемент должен описывать соответствующее структурное значение, а не просто способ его отображения. Возникает естественный вопрос: не слишком ли велика плата за достижение простой, в сущности, цели: возможности прокручивать на экране часть Веб-страницы независимо от других ее частей?

1.7.6.2. Технические доводы противников фреймов

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

  • Обозреватели по-прежнему испытывают сложности при печати фреймовых документов. Более того, эта проблема вообще не имеет единого решения. Что именно должен обозреватель выводить на принтер, когда страница содержит несколько фреймов с прокруткой: копировать текущее состояние своего окна или расширять (непонятно, правда, как) размеры фреймов, чтобы напечатать их содержимое полностью?
  • С аналогичными трудностями сталкиваются и поисковые системы — их роботы не знают, какие составляющие фреймовых документов нужно включать в результаты поиска. Например, поисковый робот системы Lycos попросту игнорирует фреймовые документы, а робот системы Alta Vista включает в результирующую базу данных все документы подряд.
  • Создание страниц с использованием фреймов намного сложнее, чем обычных HTML-документов. Это приводит к тому, что многие пользователи, не осознавая всех подводных камней, создают свои страницы с ошибками и не понимают, как от этих ошибок избавиться.

1.7.6.3. "Правильное" использование фреймов

Мы рассмотрели несколько серьезные причин, которые объясняют, почему фреймы используются сравнительно редко. Тем не менее они используются на многих Веб-узлах, и здесь мы попытаемся сформулировать правила применения фреймов, минимизирующие их недостатки.

Безусловно, наиболее безопасным является использование вложенных фреймов. В этом случае сохраняется подчиненность вложенных объектов главной странице, а поэтому не возникает проблем с адресацией страниц (хотя проблема печати содержимого вложенного фрейма все равно остается). К сожалению, на сегодняшний день элемент IFRAME поддерживается только обозревателем Internet Explorer.

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

Нам необходимо обеспечить, чтобы при переходе по гиперссылке изменялся и URI страницы в целом. Для этого нужно создать свою пару главный документ — подчиненный документ для каждого из тех документов, которые будут сменять друг друга в окне фрейма и включить атрибут target="_top" во все гиперссылки подчиненных документов, например: <A href="mylink.htm" target="_top">. Добавление этого атрибута приводит к тому, что при загрузке нового документа обозреватель удаляет все фреймы и заполняет окно новым набором фреймов. Этот набор может совпадать со старым, но URI страницы изменится на URI цели, чего мы и добиваемся! Единственное исключение: атрибут target="_top" не следует включать в ссылки на закладки, размещенные в том же документе, т. к. в этом случае нам не нужно изменения URI. Если же таких ссылок нет, то желаемого результата можно добиться еще проще: поместить в заголовок каждого подчиненного документа элемент <BASE target="_top">.

1.7.6.4. Выводы

Подведем итог сказанному в этом разделе. По нашему мнению, начинающим Веб-разработчикам фреймами не следует пользоваться вообще. Что касается профессионалов, давать им советы трудно — на то они и профессионалы. Тем не менее, мы считаем, что:

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