Статьи

Освоение CSS3 нескольких фонов

Наше путешествие в мир теней CSS3 продолжается. Сегодня мы сосредоточимся на еще одной интересной функции — как использовать несколько фонов с помощью CSS3.

Фоновая композиция

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

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

Я считаю, что у вас могут быть другие разумные аргументы 🙂

Классический подход

Поэтому нам нужно создать многослойный фон, поместив некоторые изображения поверх других. Как обычно решается эта проблема? Это действительно просто: просто создайте контейнер (например, элемент div) для каждого имеющегося изображения и добавьте для него фон, используя правило CSS. Затем вы вставляете один контейнер в другой или помещаете их в ряд и применяете соответствующие правила позиционирования CSS. У меня есть простой пример:

  <div class = "sample1">
   <div class = "sea">
     <div class = "mermaid"> <div class = "fishing"> </ div> </ div>                
     <div class = "fish"> </ div>
   </ DIV>
 </ DIV> 

Класс рыбалки внутри класса русалки только для демонстрационных целей.

И здесь у нас есть несколько стилей CSS:

  .sample1 .sea, .sample1 .mermaid, .sample1 .fishing {
    высота: 300 пикселей;
    ширина: 480 пикселей;
    положение: относительное;
 }
      

     
 .sample1 .sea {
    background: url (media / sea.png) repeat-x вверху слева;          
 }
     

      
 .sample1 .mermaid {
    фон: url (media / mermaid.svg) repeat-x внизу слева;
 }
     

  
 .sample1 .fish {
   фон: url (media / fish.svg) без повтора;
   высота: 70 пикселей;
   ширина: 100 пикселей;
   слева: 30 пикселей;
   верх: 90 пикселей;
   положение: абсолютное;
 }
     

      
 .sample1 .fishing {
   фон: url (media / fishing.svg) без повтора вверху справа 10px;
 }

Результат:

В этом примере у меня есть три вложенных div с фоновыми изображениями и еще один соседний div , fish. Вы можете представить, что рыбу можно анимировать с помощью JavaScript или CSS3-переходов или анимации.

Обратите внимание, что для класса рыбалки я использую новый синтаксис фонового позиционирования , определенный в CSS3. Но пока он поддерживается только IE9 + и Opera 11+; он еще не работает в Firefox 10 или Chrome 16. Таким образом, пользователи последних двух не могут поймать рыбу. 🙁

Давай продолжим. Можно ли упростить эту композицию?

Несколько фонов

Это когда несколько фонов приходят на сцену. Эта функция позволяет добавлять более одного фона одновременно к одному элементу. Вот как это выглядит:

  <div class = "sample2">
   <div class = "sea">                   
     <div class = "fish"> </ div>
   </ DIV>
 </ DIV> 

И стили:

  .sample2 .sea {
   высота: 300 пикселей;
   ширина: 480 пикселей;
   положение: относительное;
   background-image: url ("media / fishing.svg"), url ("media / mermaid.svg"), url ("media / sea.png");  
   background-position: вверху справа 10px, внизу слева, вверху слева;
   повторение фона: без повторения, повтор-х, повтор-х;
 }



 .sample2 .fish {
   background: url ("media / fish.svg") без повторов;
   высота: 70 пикселей;
   ширина: 100 пикселей;
   слева: 30 пикселей;
   верх: 90 пикселей;
   положение: абсолютное;
 }

Чтобы определить несколько фонов, вы должны использовать правило background-image , перечисляя ваши изображения (через запятую). Вы также можете использовать другие правила для установки положения, режима повторения и других атрибутов для каждого изображения — просто запишите их также, используя разделенный запятыми список для соответствующего правила. Обратите внимание на порядок изображений: они перечислены слева направо, начиная с самого верхнего и заканчивая самым нижним.

Результат на 100% идентичен:

В одном правиле

Если вам не нужна ваша рыба, чтобы плавать в независимом блоке, весь фон может быть записан в одном простом правиле:

  <div class = "sample3">
   <div class = "sea"> </ div>
 </ DIV> 

Стили:

  .sample3 .sea {
   высота: 300 пикселей;
   ширина: 480 пикселей;
   положение: относительное;
   background-image: url ("media / fishing.svg"), url ("media / mermaid.svg"), url ("media / fish.svg"), url ("media / sea.png");  
   background-position: верхний правый 10px, нижний левый, 30px 90px, верхний левый;
   повторение фона: без повторения, повторение х;
 } 

Я не показываю ту же картинку еще раз, но поверьте мне — она ​​равна двум изображениям выше. Посмотрите на стили еще раз, особенно на правило background-repeat . Согласно спецификации, если часть списка не указана, UA (браузер) должен повторить текущий список, чтобы заполнить остальные.

В нашем случае оно равно следующему определению:

  повторение фона: без повтора, повтор-х, без повтора, повтор-х; 

Более короткая версия

Если вы помните, в CSS2.1 можно описать фоновое изображение в одном коротком background правиле. Как насчет нескольких фонов? На самом деле, вы также можете использовать правило background для нескольких фонов:

  .sample4 .sea {
   высота: 300 пикселей;
   ширина: 480 пикселей;
   положение: относительное;
   background: url ("media / fishing.svg") вверху справа 10px без повтора,
               url ("media / mermaid.svg") слева внизу repeat-x,
               url ("media / fish.svg") 30px 90px без повтора,
               url ("media / sea.png") repeat-x;                
 } 

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

Динамические изображения

Вот что мы уже знаем: если ваш фон в основном статичен — это может зависеть от размера контейнера (т. Е. Если вы используете% length, чтобы некоторые слои сместились при изменении размера окна), — тогда магия нескольких фонов полезна, так как действительно упрощает структуру страницы. Но что, если вам нужно анимировать некоторые слои с помощью JavaScript (перемещение, вращение и т. Д.)?

У меня есть пример из реальной жизни — тема одуванчиков на сайте Яндекса (российский поисковый провайдер, YNDX ):

Если вы посмотрите на исходный код (нажмите F12 в IE, чтобы открыть devtools ), вы найдете код, подобный следующему:

  <div class = b-skin-bg sizcache = "272" sizset = "0">
   <Div class = b-fluff-bg sizcache = "272" sizset = "0">
 <Div class = b-fluff__sky sizcache = "272" sizset = "0">
       <Div style = "background-position: 3244px 0px" class = b-fluff__cloud> </ div>
         <Div style = "width: 1200px" class = b-max-width sizcache = "214" sizset = "0">
           <div class = b-fluff__placeholder sizcache = "302" sizset = "0">
           <div style = "bottom: 105px; отображение: нет; слева: 940px" class = "b-fluff__item b-fluff_item_3" jQuery1328289994769 = "30"> </ div>
           <Div style = "bottom: 50px; отображение: нет; слева: 879px" class = "b-fluff__item b-fluff_item_3" jQuery1328289994769 = "31"> </ div>
           <Div style = "bottom: 105px; отображение: нет; слева: 940px" class = "b-fluff__item b-fluff_item_3" jQuery1328289994769 = "32"> </ div>
 ...
         </ DIV>
       </ DIV>
     </ DIV>
   </ DIV>
 </ DIV> 

К div с классами b-fluff-bg, b-fluff__cloud & b-fluff__item применяются правила CSS, добавляющие наложенные фоновые изображения. Фон с облачной прокруткой слева направо, а фон с семенами одуванчика летит по экрану.

Можно ли переписать такую ​​композицию, используя CSS3 несколько фонов? На самом деле, да, но только если 1) он поддерживается во всех целевых браузерах и 2) продолжить чтение;)

Как мы можем сделать наши многочисленные фоны более динамичными? Внутри браузер разбирает каждое background правило на отдельные правила background-* для каждого из атрибутов. Это очень полезно, если вам нужно изменить только один из атрибутов. Например, вы можете использовать правило background-position для смещения ваших изображений. Но есть некоторые штрафы за работу с несколькими фонами: если вы собираетесь переместить только один слой, вам все равно нужно переписать это правило для всех слоев.

Для анимации нашего морского фона мы можем использовать следующий код JavaScript:

  $ (документ) .ready (function () {
   var sea = $ (". sample5 .sea") [0];
   var fishesX = 30;
   var fishesY = 90;
   var fishX = 0;
   var fishY = 0;
   var mermaidX = 0;
   var t = 0;
 
   function animationLoop () {
       fishesY = 90 + Math.floor (30 * Math.sin (t ++ / 180.0));
       if (- fishesX 480) mermaidX = 0;
       fishY = -10 + (10 * Math.cos (t * 0,091));
       fishX = 10 + (5 * Math.sin (t * 0,07));
 
       sea.style.backgroundPosition = "top" + fishY + "px right" + fishX + "px," + mermaidX + "px bottom", + fishesX + "px" + fishesY + "px, top left";
 
       window.requestAnimFrame (animationLoop);
   }
   animationLoop ();
 }); 

Где:

  window.requestAnimFrame = (function () {
   возвращение
       window.requestAnimationFrame ||
       window.msRequestAnimationFrame ||
       window.mozRequestAnimationFrame ||
       window.oRequestAnimationFrame ||
       window.webkitRequestAnimationFrame ||
       (function (callback) {window.setTimeout (callback, 1000/60);});
 }) (); 

Результат ( видео ):

Вы также можете использовать CSS3 Transitions или Animations, но это хорошая тема для отдельного обсуждения.

Параллакс и Интерактивность

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

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

  sea.style.backgroundPosition = "top" + fishY + "px right" + fishX + "px," + mermaidX + "px bottom", + fishesX + "px" + fishesY + "px, top left"; 

Я уверен, что можно создать хорошую и полезную библиотеку JavaScript, которая виртуализирует все эти слои и обеспечит простой способ изменения атрибутов для отдельного слоя, сохраняя чистоту вашего HTML-кода и DOM.

Совместимость

Все современные браузеры, включая IE10 и 9, поддерживают несколько фонов. Вы также можете использовать некоторые инструменты, такие как Modernizr, чтобы обеспечить некоторый уровень совместимости для старых браузеров, например, предоставляя альтернативный фон. Как написал Крис Койер в своей статье о порядке наложения нескольких фонов , вы можете использовать следующий подход:

  .multiplebgs body {
   / * Потрясающие множественные декларации BG, которые выходят за рамки реальности и производят впечатление на цыпочек * /
 }



 .no-multipbgs body {
   / * laaaaaame резервный * /
 } 

Если вас не устраивает использование JavaScript для обеспечения обратной совместимости для новых правил CSS3, вы можете просто определить свойство background дважды (но этот подход может привести к ненужным загрузкам для современных браузеров, в зависимости от того, как они обрабатывают такие правила):

  / * многократный откат BG * /
 фон: # 000 url (...) ...;
 / * Потрясающие множественные декларации BG, которые выходят за рамки реальности и производят впечатление на цыпочек * /
 фон: url (...), url (...), url (...), # 000 url (...); 

И, наконец, если вы хотите это знать: да, вы можете использовать несколько фонов в своих приложениях в стиле Metro для Windows 8, созданных с использованием HTML и JavaScript.

PS Посмотрите эту феноменальную статью Алекса Уокера о принципе цикады.

Заметка
Свойства CSS, обсуждаемые в этой статье, определяются в модуле « Фоны и границы CSS3 », который в настоящее время находится в состоянии «Рабочий чертёж». Между тем, он кажется достаточно стабильным, но все еще может измениться в деталях.