Статьи

DOM-foolery с изображениями

Рискнув повториться тем, кто читает представление «Дизайн», я решил опубликовать эту небольшую идею из вчерашнего номера.

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

В прошлом не было большого выбора. Вы создали красивый шаблон для создания кадров в Photoshop или Fireworks, поместили свое изображение за ним и экспортировали новое изображение.

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

Итак, каковы альтернативы? Оказывается, даже стили CSS3 или Mozilla не могут нам помочь. Моз может сделать границы, которые изгибаются за углами — достаточно красивый вид, но не то, что мы здесь. Safari может содержать несколько фонов, но в других местах его не так много. Мне показалось, что единственное жизнеспособное решение — это «DOM-foolery».

Пример проблемы Во-первых, нам нужно разработать повторяемый метод, чтобы получить эффект, забыв (на данный момент) о технике звуковой разметки.

Поскольку изображения являются элементами переднего плана, нам нужно поднять нашу «угловую графику» над изображением . Это означает, что нам нужно обернуть каждое изображение собственным «относительно позиционированным» DIV, а затем использовать эту «обертку» для позиционирования наших «абсолютно позиционированных» углов.

Как вы можете видеть на диаграмме, DIV-оболочка называется «.wrapper» и должна располагаться относительно и перемещаться влево или вправо, чтобы она плотно закрывала наше изображение.

div.wrapper { position:relative; float:left; } 

Наши четыре внутренних DIV затем устанавливаются в « position: absolute », что автоматически выводит их на передний план нашего изображения. Каждый имеет одинаковую ширину и высоту (7x7px — размеры угловых GIF-файлов), но разные позиции и фоновую графику. Что-то вроде этого:

 div.wrapper div{ /* set all the inner DIVs */ position:absolute; width: 7px; height: 7px; } div.wrapper div.tl{ background:transparent url(tl.gif) top left no-repeat; left:0; top:0 } div.wrapper div.tr{ background:transparent url(tr.gif) top right no-repeat; right:0; top:0 } div.wrapper div.bl{ background:transparent url(bl.gif) bottom left no-repeat; left:0; bottom:0 } div.wrapper div.br{ background:transparent url(br.gif) bottom right no-repeat; right:0; bottom:0 } направо div.wrapper div{ /* set all the inner DIVs */ position:absolute; width: 7px; height: 7px; } div.wrapper div.tl{ background:transparent url(tl.gif) top left no-repeat; left:0; top:0 } div.wrapper div.tr{ background:transparent url(tr.gif) top right no-repeat; right:0; top:0 } div.wrapper div.bl{ background:transparent url(bl.gif) bottom left no-repeat; left:0; bottom:0 } div.wrapper div.br{ background:transparent url(br.gif) bottom right no-repeat; right:0; bottom:0 } направо div.wrapper div{ /* set all the inner DIVs */ position:absolute; width: 7px; height: 7px; } div.wrapper div.tl{ background:transparent url(tl.gif) top left no-repeat; left:0; top:0 } div.wrapper div.tr{ background:transparent url(tr.gif) top right no-repeat; right:0; top:0 } div.wrapper div.bl{ background:transparent url(bl.gif) bottom left no-repeat; left:0; bottom:0 } div.wrapper div.br{ background:transparent url(br.gif) bottom right no-repeat; right:0; bottom:0 } 

Скомбинируйте разметку с CSS , и она прекрасно сочетается.

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

В нашем случае мы решили настроить таргетинг только на изображения в указанном « DIV # контенте » — области редактируемого контента CMS. Однако не составит труда изменить сценарий так, чтобы он предназначался для всех изображений или только для изображений определенного класса, если это необходимо.

Я быстро пробежусь по сценарию, но пример хорошо прокомментирован, если вам интересно

Для начала мы объявим новую функцию (roundedImages), возьмем все элементы внутри #content, затем отфильтруем все, кроме изображений. Они ждут, чтобы мы использовали их в массиве imgs [].

function roundedImages() { var content = document.getElementById ('content'); var imgs = content.getElementsByTagName ('img');
function roundedImages() { var content = document.getElementById ('content'); var imgs = content.getElementsByTagName ('img'); 

Далее мы запускаем цикл для обработки нашего списка изображений. Мы создаем новый DIV, прикрепляем к нему класс «обертка», выбираем первое изображение и заменяем его (на данный момент) нашим новым DIV.

for (var i = 0; i 

Теперь нам нужно внедрить наши четыре угловых DIV в документ и прикрепить соответствующие классы к каждому. Код довольно прост.

var tl = document.createElement('div'); tl.className ='tl'; var br = document.createElement('div'); br.className ='br'; var tr = document.createElement('div'); tr.className ='tr'; var bl = document.createElement('div'); bl.className ='bl';
var tl = document.createElement('div'); tl.className ='tl'; var br = document.createElement('div'); br.className ='br'; var tr = document.createElement('div'); tr.className ='tr'; var bl = document.createElement('div'); bl.className ='bl'; 

Хорошо, у нас есть свои угловые DIV, но их на самом деле нет в документе. Мы можем использовать ‘ appendChild ‘, чтобы склеить их в нашу оболочку DIV. Чтобы завершить цикл, мы склеиваем наше оригинальное изображение обратно в обертку; тогда мы готовы захватить следующее изображение.

 wrapper.appendChild(tl); wrapper.appendChild(tr); wrapper.appendChild(bl); wrapper.appendChild(br); wrapper.appendChild(original); } } 

Наконец, мы запускаем функцию при загрузке страницы.

window.onload = roundedImages; 

Вот и все. Вставьте скрипт в свой <head> с помощью CSS, и вы закругляете углы, как драйвер INDY500. Вы можете увидеть это в действии здесь .

Насколько мне известно, он работает как шарм в IE5 +, Moz1 +, Safari и Opera 8.0. Кажется, в Opera 7 есть ошибка, которую я еще не понял.

Это, конечно, эксперимент первого поколения и имеет некоторые ограничения. DIV.wrapper’ должен быть плавающим, чтобы плотно окружить изображение, что означает, что ваши изображения всегда будут казаться плавающими. Однако было бы вполне возможно снять это требование, если скрипт вытащит размеры каждого изображения, а затем использует их для ручного определения размера оболочки.

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

В IE6 также есть странная ошибка (Нет! Никогда! ), Которая вызывает неправильное выравнивание на 1 пиксель по правой и нижней сторонам изображений с нечетной шириной и высотой. Совершенно странно. Кажется, это ошибка округления (без каламбура), и на данный момент лучшее решение, которое я могу предложить, — это использовать четные размеры изображения. Если у вас есть лучший IE вуду, мы бы с удовольствием его услышали.

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

У меня есть некоторые идеи для некоторых вариантов, которые я мог бы рассмотреть в следующем посте, но дайте мне знать, если вы найдете это полезным.

PostScript

С некоторыми отличными предложениями от Джошуа Пейна , мы внесли несколько небольших улучшений в этот скрипт.

  • Во-первых, ошибка округления в IE приводила к тому, что углы располагались с « right:o », выполняя выравнивание на 1 пиксель в зависимости от ширины браузера). Исправление заключается в том, чтобы верхний правый и нижний правый углы растягивали всю ширину обертки и вместо этого выравнивали фоновое изображение по правой стороне. Для этого нам нужно использовать DOM, чтобы принудительно установить ширину каждой обертки в ширину содержащегося в ней изображения — изначально мы не указывали ее ширину
  • Довольно часто хочется связать изображения. Это вызывает «переупорядочение дерева», и вещи больше не там, где они ожидают ошибок поиска. Мы добавили строку, чтобы заставить скрипт переходить по ссылке.

Оба эти предложения теперь включены в пример . Спасибо, Джошуа.