Процентные значения для CSS свойства background-position.

Перевод статьи:  CSS background-position and percent.
Автор:  Roger Johansson.

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

Изначально, дизайн сайта, который мне пришлось переделывать, был фиксированным. Одна из предусмотренных им колонок имела цветной фон, который независимо от имеющегося в колонке контента занимал весь ее объем — от шапки до подвала. Для реализации этого элемента использовалось фоновое изображение в стиле à la Faux Columns («фиктивные колонки»). Мне нужно было придать данной конструкции свойство гибкости, предусмотренное требованиями нового адаптивного дизайна.

Дело в том, что гибкий контроль ширины и смена ее фиксированных пиксельных значений на процентные применительно к фоновым изображениям элементов, используемым для такой имитации колонок, имеет свои нюансы. Это связано с тем, как ведет себя свойство background-position в случае применения к нему процентных значений, скажем таких как background-position: 40% 0.

Вы, вероятно, думаете, что взятое в качестве значения процентное отношение сообщает браузеру точку элемента, где должно позиционироваться фоновое изображение (*то есть его левый верхний угол, или другими словами координаты left:0 и top:0 самого изображения). Но это не совсем так. Указываемые вами в данном случае значения применяются как к самому элементу, так, собственно, и к используемому в качестве его фона изображению. Вот что об этом говориться в спецификации CSS 2.1:

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

Проблемы, вызываемые процентными значениями.

Я заметил, что на практике при использовании процентных величин в качестве значений для свойства background-position, зачастую очень сложно добиться желаемого результата. Что касается моего личного опыта, то для меня более привычны ситуации, когда необходимо совместить точку, соответствующую X% ширины изображения с точкой, отмеряющей Y% ширины форматируемого элемента, причем с различными X и Y значениями. Такую схему можно реализовать путем добавления явного смещения начальной точке фонового изображения таким образом, чтобы его полная ширина была равна ширине элемента, к которому оно применяется. В результате чего точка, соответствующая X% ширины изображения будет перемещаться пропорционально с точкой X% ширины (или горизонтальной координаты) содержащего его блока. Грубовато, конечно, но выполнимо. Именно таким образом я и поступил в процессе модернизации шаблона сайта до адаптивного.

Это работает до того момента, пока ширина рабочей области браузера (или вьюпорт) не достигнет точки, которая требует смены пропорций ширины колонок макета страницы, что предусмотрено адаптивным дизайном. После этого пересчет процентных значений X% ширины изображения и X% ширины элемента будут иметь различные пиксельные эквиваленты. Если ширина области элемента-контейнера известна, то можно определить процентное значение, позволяющее добиться корректного совмещения точек, но как только произойдет следующая смена соотношений размеров колонок, вызванная изменением ширины вьюпорта, фоновое изображение снова не будет соответствовать требуемой ширине колонки.

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

Если изначальный размер окна браузера больше 1000 пикселей, и вы плавно уменьшаете его, то размеры колонок фонового изображения (левая темно-зеленого цвета со светло-зеленой правой границей и правая белая колонка) будут в точности соответствовать ширине плавающих блоков (CSS колонок). Но что произойдет, когда окно браузера уменьшится до размеров 800px, 600px и 500px, которые являются контрольными точками, представляющими размеры дисплеев различных устройств, при достижении которых соотношение ширины колонок меняется? Это приведет к дисбалансу размеров колонок фонового изображения и тех, которые образованы плавающими блоками (CSS колонками) в первом макете.

Существует не совсем удачное, грубое решение данной проблемы, а именно — загрузка нового изображения, предусмотренного для каждого конкретного случая смены пропорций размеров колонок. И я мог бы поступить таким образом. Но что, если возникнет необходимость смены пропорций снова? Тогда придется создавать новое изображение и добавлять его к списку загружаемых браузером ресурсов. Я хотел по возможности обойти эти неудобства.

В итоге ситуацию спасает функция calc().

После многочисленных экспериментов с функцией calc(), мне всё-таки удалось создать требуемое математическое выражение, позволяющее вычислять процентные значения для свойства background-position фонового изображения элемента в тех случаях, когда пропорции представленных им колонок не соответствуют пропорциям реальных CSS колонок, образуемых плавающими элементами.

На моей демо-странице в примере задействовано изображение шириной 1000px, которое разбито на две колонки — зеленую (400px) и белую (600px). В том случае, если CSS колонки имеют такие же пропорции (40% и 60%), то для корректного позиционирования фонового изображения можно обойтись простой декларацией background-position: 40% 0, но если колонки, образуемые плавающими элементами, будут иметь другие пропорции их ширины, то этого будет не достаточно. Тогда на помощь придет следующий прием:

#container {
background-image:url(bg.png);
background-repeat:repeat-y;
background-position:calc(25% — (400px — 1000px * 0.25)) 0;
/* [ширина первой CSS колонки]% — ([ширина первой колонки изображения]px — [полная ширина изображения]px * [доля ширины первой CSS колонки от общей ширины элемента в десятичной форме]) */
}

Если пропорции CSS колонок изменятся, скажем, на 67% и 33%, то все что вам нужно будет сделать, это заменить значение 25% на 67% и 0.25 на 0.67. Представленное выше выражение разрабатывалось мной лично на основе собственных математических познаний и довольно неплохо работает, но если вы обнаружите в нем какие-либо ошибки, пожалуйста, сообщите.

Осталось выяснить, можно ли использовать результаты вычисления функции calc() в качестве значений для CSS свойств. В реальности поддержка этой функции в браузерах несколько лучше, чем я ожидал (IE9+, Chrome 19+, Safari 6+, Firefox 4+), особенно если вы используете ее в рамках блоков медиа запросов, не поддерживаемых в IE8-. Среди распространенных браузеров, не обеспечивающих поддержку, можно выделить: Safari 5- для OS X и iOS; Opera (все варианты — Desktop, Mobile и Mini); а также браузер системы Android. Поэтому, если для вас очень важен вопрос корректного позиционирования фонового изображения в этих браузерах, то вам, скорее всего, понадобиться загружать отдельные изображения для различных ситуаций или же искать другой способ решения проблемы.

Неплохо было бы обзавестись свойством background-origo.

Помимо функции calc(), которая, по-видимому, позволяет решить данную проблему, хотелось бы увидеть более интуитивно понятный вариант, то есть позволяющий явно указывать точку изображения, которая должна совпасть с точкой его позиционирования в рамках элемента. Мой коллега Антон, к примеру, предложил на эту роль свойство, назвав его background-origo, которое позволило бы использовать следующую конструкцию:

.container {
background-position:25% 0;
background-origo:400px 0;
}

В результате чего точка, соответствующая 400px ширины изображения всегда будет совпадать с точкой, находящейся на отметке 25%-ой ширины элемента. Что касается исходного значения для этого свойства, то здесь вполне резонно допустить то значение, которое предусмотрено свойством background-position касательно позиции в фоновом изображении.

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

* Примечание переводчика.

Один комментарий на Процентные значения для CSS свойства background-position.

  1. Чтобы указать, где именно внутри области позиционирования будет находиться фоновое изображение, этой области необходима система координат, используемая для преобразования в неё значений background-position. Прежде чем двигаться дальше, давайте повнимательнее рассмотрим эту систему координат.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *