Реальное применение свойства clip для формирования визуального эффекта
В предыдущем уроке мы рассказали о замечательном свойстве CSS clip
и функции rect()
. Теперь рассмотрим практическое применение описанного свойства. Создадим прелестный и простой эффект для скрытия части содержания и вывода его полностью на весь экран.
Мы продемонстрируем использование свойства CSS clip
для формирования плавного перехода при нажатии на прямоугольном элементе. Идея заключается в выводе покрывающего слоя так, как будто он скрывается под соответствующим элементом. Нажатие на элемент удаляет его с экрана, открывая покрывающий слой, который разворачивается на все окно.
Сначала создаем список пунктов, оформленных в стиле прямоугольников Metro:
Каждый прямоугольник содержит элемент (покрывающий слой), который позиционируется фиксировано. Данный элемент в действительности раскрыт над все страницей, но для него установлена полная прозрачность. При нажатии на прямоугольник используется clip: rect()
для обрезки соответствующей части внутренного фиксированного элемента. Затем происходит анимация расширения обрезанной части до полных ширины и высоты покрывающего слоя, которые соответствуют размерам окна просмотра:
Нажатие на кнопке закрытия вызовет реверс эффекта, и покрывающий слой свернется до размеров пункта списка и исчезнет.
Разметка HTML
Для прямоугольников будем использовать неупорядоченный список. Каждый пункт списка имеет класс иконки и опциональный класс “span”, который управляет шириной прямоугольника. Внутрь мы добавляем текст и элемент div
покрывного слоя. Покрывной слой имеет структуру табличного шаблона. Для примера мы выбрали тему погоды, поэтому на покрывном слое представлена имитация прогноза на 7 дней. Каждый столбец дня имеет несколько элементов span
, которые используются для указания дня недели, иконки погоды и температуры.
<ul id="rb-grid" class="rb-grid clearfix"> <li class="icon-clima-1 rb-span-2"> <h3>Лиссабон</h3> <span class="rb-temp">21°C</span> <div class="rb-overlay"> <span class="rb-close">close</span> <div class="rb-week"> <div><span class="rb-city">Лиссабон</span><span class="icon-clima-1"></span><span>21°C</span></div> <div><span>Пн</span><span class="icon-clima-1"></span><span>19°C</span></div> <div><span>Вт</span><span class="icon-clima-2"></span><span>19°C</span></div> <div><span>Ср</span><span class="icon-clima-2"></span><span>18°C</span></div> <div><span>Чт</span><span class="icon-clima-2"></span><span>17°C</span></div> <div><span>Пт</span><span class="icon-clima-1"></span><span>19°C</span></div> <div><span>Сб</span><span class="icon-clima-1"></span><span>22°C</span></div> <div><span>Вс</span><span class="icon-clima-1"></span><span>18°C</span></div> </div> </div> </li> <li class="icon-clima-2"> <h3>Париж</h3><span class="rb-temp">11°C</span> <div class="rb-overlay"> <!-- ... --> </div> </li> <li><!-- ... --></li> <!-- ... --> </ul>
CSS
В тексте урока опущены префиксы браузеров. Полный код можно посмотреть в исходниках.
Неупорядоченный список центрируется в родительском элементе и для него удаляются стили списка:
.rb-grid { list-style: none; text-align: center; margin: 0 auto; }
Пункты списка имеют плавающую ширину и высоту в 15em. Они будут сдвигаться влево:
.rb-grid li { width: 24%; height: 15em; margin: 0.5%; background: #8CC7DF; color: #fff; display: block; float: left; padding: 1.6em; cursor: pointer; position: relative; }
Существует три различных ширины для пунктов нашей сетки. По умолчанию один вариант 24%, а остальные два определяются так:
.rb-grid li.rb-span-2 { width: 49%; } .rb-grid li.rb-span-4 { width: 99%; }
Определяем заголовок с названием города:
.rb-grid li h3 { font-size: 2.6em; font-weight: 100; }
Включаем файл CSS для иконок, которые будут использоваться на странице. Это шрифт Climacons (автор Adam Whitcroft). Вы можете просмотреть файл climacons.css, чтобы понять,какие иконки мы включили. Для добавления иконок с помощью псевдо элемента мы используем класс иконок.. В нашей сетке они будут позиционироваться абсолютно в правом нижнем углу и выводиться с небольшим усечением:
.rb-grid li[class^="icon-"]:before, .rb-grid li[class*=" icon-"]:before { font-size: 10em; position: absolute; display: block; width: 100%; height: 100%; top: 0; left: 0; line-height: 3; opacity: 0.4; text-align: right; pointer-events: none; }
Температура будет полупрозрачной и мы используем переход для установки уровня видимости:
.rb-temp { display: block; font-size: 2em; opacity: 0.5; transition: all 0.3s ease-in-out; }
При наведении на пункт списка мы просто увеличим непрозрачность:
.rb-grid li:hover .rb-temp { opacity: 1; }
Теперь рассмотрим важный элемент div
покрывного слоя. Конечный вид будет распространяться на весь экран, поэтому установим ширину и высоту 100%. Он должен располагаться поверх всего на экране, поэтому определяем для него фиксированное позиционирование. Начальное значение свойства z-index
устанавливаем равным -1. Таким образом покрывной слой помещается за содержанием страницы, а установка непрозрачности равной 0 делает его невидимым:
.rb-overlay { opacity: 0; position: fixed; top: 0; left: 0; width: 100%; height: 100%; transition: all 0.4s ease; z-index: -1; pointer-events: none; cursor: default; }
Это исходное состояние покрывного слоя. Как только мы нажмем на пункте списка, нужно установить правильные значения функции rect()
для свойства clip
и расширяем покрывной слой с помощью анимации.
Рассмотрим остальные стили.
Каждый покрывной слой имеет небольшую кнопку “закрыть”, которая позиционируется в верхнем правом углу.
.rb-close { position: absolute; top: 0.4em; right: 0.4em; width: 2em; height: 2em; text-indent: -9000px; cursor: pointer; z-index: 1000; } .rb-close:before { content: 'x'; font-weight: 100; position: absolute; top: 0; left: 0; width: 100%; height: 100%; font-size: 3em; line-height: 0.6; text-align: center; text-indent: 0px; }
Контейнер для столбца имеет класс rb-week (хотя мы также включаем колонку текущей погоды). Нужно установить ширину и высоту 100%, чтобы можно было определять высоту и ширину элементов наследников:
.rb-week { width: 100%; height: 100%; }
Колонки будут иметь ширину 10% (за исключением первой, которая имеет ширину 30%) и будут смещаться влево:
.rb-week > div { width: 10%; height: 100%; float: left; position: relative; padding: 3% 0; } .rb-week > div:first-child { width: 30%; }
У нас есть восемь колонок: 7 из них занимают 70% (7 раз по 10%), а восьмая - 30%.
Каждый элемент span
имеет высоту 30% и небольшой отступ:
.rb-week span { padding: 5% 0; font-size: 2em; font-weight: 100; display: block; margin: auto 0; height: 30%; width: 100%; line-height: 0.8; }
Элемент span
для имени города имеет специальный стиль с более легким шрифтом:
.rb-week span.rb-city { font-weight: 700; padding: 1% 10%; font-size: 1em; line-height: 1.2; }
Иконки имеют увеличенный размер шрифта и нужно сбросить его вес, который изменяется другими правилами:
.rb-week [class^="icon-"]:before { font-size: 2.5em; font-weight: normal; }
Колонка текущей погоды будет почти прозрачной:
.rb-week > div:first-child [class^="icon-"] { opacity: 0.1; }
Теперь определим разные цвета фона для каждого прямоугольника и каждой колонки в покрывном слое.
У нас есть 11 пунктов списка:
/* Цвета */ /* Сетка */ .rb-grid li:nth-child(1) { background: #3399CC; } .rb-grid li:nth-child(2) { background: #33CCCC; } .rb-grid li:nth-child(3) { background: #996699; } .rb-grid li:nth-child(4) { background: #C24747; } .rb-grid li:nth-child(5) { background: #e2674a; } .rb-grid li:nth-child(6) { background: #FFCC66; } .rb-grid li:nth-child(7) { background: #99CC99; } .rb-grid li:nth-child(8) { background: #669999; } .rb-grid li:nth-child(9) { background: #CC6699; } .rb-grid li:nth-child(10) { background: #339966; } .rb-grid li:nth-child(11) { background: #666699; }
И каждый покрывной слой имеет восемь колонок:
/* Колонки в покрывном слое */ .rb-grid li:nth-child(1) .rb-week > div:nth-child(1) { background: #3399CC; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(2) { background: #2D87B4; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(3) { background: #297AA3; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(4) { background: #256E93; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(5) { background: #216283; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(6) { background: #1D5672; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(7) { background: #184962; } .rb-grid li:nth-child(1) .rb-week > div:nth-child(8) { background: #143D52; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(1) { background: #33CCCC; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(2) { background: #2DB4B4; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(3) { background: #29A3A3; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(4) { background: #259393; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(5) { background: #218383; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(6) { background: #1D7272; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(7) { background: #186262; } .rb-grid li:nth-child(2) .rb-week > div:nth-child(8) { background: #145252; } /* ... */
…и так lzk всех 11 прямоугольников.
И в завершении воспользуемся медиа запросами для маленьких экранов.
Когда пространство ограничено, то не нужно выводить прямоугольники в сетке.
@media screen and (max-width: 63.125em) { .rb-grid li, .rb-grid li.rb-span-2, .rb-grid li.rb-span-4 { width: 100%; height: 10em; text-align: left; } .rb-grid li[class^="icon-"]:before, .rb-grid li[class*=" icon-"]:before { font-size: 6em; left: auto; right: 0; line-height: 2.5; } .rb-grid li > div { text-align: center; } }
Колонки покрывного слоя и текст в них будут формироваться с помощью плагина FitText, поэтому шаблон не будет меняться драматически.
JavaScript
Начнем с кеширования элементов и инициализации переменных:
var $items = $( '#rb-grid > li' ), transEndEventNames = { 'WebkitTransition' : 'webkitTransitionEnd', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionEnd', 'msTransition' : 'MSTransitionEnd', 'transition' : 'transitionend' }, // Название перехода и события transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ], // Элементы window и body $window = $( window ), $body = $( 'BODY' ), // Поддержка переходов supportTransitions = Modernizr.csstransitions, // Индекс текущего элемента current = -1, // Ширина и высота окна winsize = getWindowSize();
Сначала мы применяем плагин jQuery FitText к элементам текста колонок в покровным слое, чтобы масштабировать текст в соответствии с размером экрана.
Затем привязываем событие click к пунктам и кнопки закрытия.
Также нужно получить текущее значение для ширины и высоты окна и привязать событие resize к элементу окна.
function init( options ) { // Применяем плагин fittext $items.find( 'div.rb-week > div span' ).fitText( 0.3 ).end().find( 'span.rb-city' ).fitText( 0.5 ); initEvents(); }
Когда происходит нажатие на пункте, запускаются два перехода для соответствующего покровного элемента. Первый применяет свойство clip
, которое обрезает покровный слой точно по размерам прямоугольника. Также покровный слой будет изменять прозрачность. Второй переход выполняет анимацию расширения покровного слоя на все окно. Для первого перехода значения должны соответсвовать положению и размерам пункта списка. Мы получаем значения вызывая функцию “getItemLayoutProp”. Для второго слоя нам нужна только ширина и высота окна для определения правильных значений.
Также нужно принять во внимание два момента. Первое, мы скрываем прокрутку страницы в промежуточном состоянии, так как не нужно, чтобы кто-нибудь прокручивал страницу до завершения перехода (расширения покровного слоя). Второе покровной слой имеет свойство z-index с большим значением, чтобы всегда оставаться сверху, и свойство pointer-events имеет значение auto, чтобы покровной слой принимал события click. Если переходы не поддерживаются, первое состояние пропускается и покровной слой сразу расширяется до полного размера.
function initEvents() { $items.each( function() { var $item = $( this ), $close = $item.find( 'span.rb-close' ), $overlay = $item.children( 'div.rb-overlay' ); $item.on( 'click', function() { if( $item.data( 'isExpanded' ) ) { return false; } $item.data( 'isExpanded', true ); // Сохраняем текущий индекс пункта current = $item.index(); var layoutProp = getItemLayoutProp( $item ), clipPropFirst = 'rect(' + layoutProp.top + 'px ' + ( layoutProp.left + layoutProp.width ) + 'px ' + ( layoutProp.top + layoutProp.height ) + 'px ' + layoutProp.left + 'px)', clipPropLast = 'rect(0px ' + winsize.width + 'px ' + winsize.height + 'px 0px)'; $overlay.css( { clip : supportTransitions ? clipPropFirst : clipPropLast, opacity : 1, zIndex: 9999, pointerEvents : 'auto' } ); if( supportTransitions ) { $overlay.on( transEndEventName, function() { $overlay.off( transEndEventName ); setTimeout( function() { $overlay.css( 'clip', clipPropLast ).on( transEndEventName, function() { $overlay.off( transEndEventName ); $body.css( 'overflow-y', 'hidden' ); } ); }, 25 ); } ); } else { $body.css( 'overflow-y', 'hidden' ); } } ); ... } ); ... } function getItemLayoutProp( $item ) { var scrollT = $window.scrollTop(), scrollL = $window.scrollLeft(), itemOffset = $item.offset(); return { left : itemOffset.left - scrollL, top : itemOffset.top - scrollT, width : $item.outerWidth(), height : $item.outerHeight() }; }
При нажатии кнопки "закрыть" все происходит в обратном порядке:
function initEvents() { $items.each( function() { ... $close.on( 'click', function() { $body.css( 'overflow-y', 'auto' ); var layoutProp = getItemLayoutProp( $item ), clipPropFirst = 'rect(' + layoutProp.top + 'px ' + ( layoutProp.left + layoutProp.width ) + 'px ' + ( layoutProp.top + layoutProp.height ) + 'px ' + layoutProp.left + 'px)', clipPropLast = 'auto'; // Сбрасывает текущее значение current = -1; $overlay.css( { clip : supportTransitions ? clipPropFirst : clipPropLast, opacity : supportTransitions ? 1 : 0, pointerEvents : 'none' } ); if( supportTransitions ) { $overlay.on( transEndEventName, function() { $overlay.off( transEndEventName ); setTimeout( function() { $overlay.css( 'opacity', 0 ).on( transEndEventName, function() { $overlay.off( transEndEventName ).css( { clip : clipPropLast, zIndex: -1 } ); $item.data( 'isExpanded', false ); } ); }, 25 ); } ); } else { $overlay.css( 'z-index', -1 ); $item.data( 'isExpanded', false ); } return false; } ); } ); ... }
Готово!
Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/1HAjyTPJdek/lessons.php
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-11-26 » Капитан грузового судна, или Как начать использовать Docker в своих проектах
- 2024-11-26 » Обеспечение безопасности ваших веб-приложений с помощью PHP OOP и PDO
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-15 » Перенос сайта на WordPress с одного домена на другой
- 2024-11-08 » OSPanel 6: быстрый старт
- 2024-11-08 » Как установить PhpMyAdmin в Open Server Panel
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
- 2024-06-11 » Скорость загрузки сайта: почему это важно и как влияет на ранжирование
Великие умы обсуждают идеи, средние - обсуждают поступки, а малые - людей Индийская пословица |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.