Статьи автора Olga мне очень нравятся лаконичностью и полнотой освещения темы. Всё же нашелся дяденька, который пошел дальше, в его примерах(к сожалению — переводных, молодцы всё-таки «проклятые буржуины») можно не только подсмотреть реализацию многих интересных преобразований HTML без JavaScript опираясь лишь на возможности CSS. Разумеется, тут ни для кого нет новой полезной информации. Я хотел бы попросить [Olga] и всех — кто помогает новичкам вникать в тайны CSS делать в своих публикациях с демонстрацией кода такие вот комментарии:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Language" content="ru" /> <title>Пример слайдера, управляемого только с помощью CSS3</title> </head> <style type="text/css"> /* ==================== ОТВЛЕЧЁННОЕ: сброс стилей ==================== */ * { border: 0 solid; /* украшательство */ margin: 0; /* украшательство */ padding: 0; /* украшательство */ outline: 0; /* украшательство */ -moz-box-sizing: border-box; /* украшательство */ -webkit-box-sizing: border-box; /* украшательство */ box-sizing: border-box; /* украшательство */ } body { background: #eee; /* украшательство */ font-family: Verdana, Tahoma, Arial; /* украшательство */ font-size: 10pt; /* украшательство */ padding: 15px; /* украшательство */ text-align: center; /* украшательство */ overflow: scroll; /* украшательство */ } a { color: #c00; /* украшательство */ font-weight: bold; /* украшательство */ text-decoration: underline; /* украшательство */ } a:hover { text-decoration: none; /* украшательство */ } /* ==================== КОНТЕНТ: левая выпадающая панель ==================== */ #left { position: absolute; /* панель будем позиционировать */ right: 50%; /* двигаем на центр и оталкивается справа налево */ margin-right: 240px; /* отодвигаем влево за слайдер (половина его ширины) */ overflow: hidden; /* выступающие части контента отсекаем */ background: #ddd; /* украшательство */ border: #ccc 1px solid; /* украшательство */ border-right: none; /* украшательство */ margin-top: 15px; /* украшательство */ width: 25px; /* украшательство */ min-height: 250px; /* украшательство */ text-align: left; /* украшательство */ } #left > div { display: none; /* контент панели изначально скрыт */ margin-top: 25px; /* украшательство */ padding: 15px; /* украшательство */ } /* ==================== КОНТЕНТ: правая выпадающая панель ==================== */ #right { position: absolute; /* панель будем позиционировать */ left: 50%; /* двигаем на центр и оталкивается слева направо */ margin-left: 240px; /* отодвигаем вправо за слайдер (половина его ширины) */ overflow: hidden; /* выступающие части контента отсекаем */ background: #ddd; /* украшательство */ border: #ccc 1px solid; /* украшательство */ border-left: none; /* украшательство */ margin-top: 15px; /* украшательство */ width: 25px; /* украшательство */ min-height: 250px; /* украшательство */ text-align: left; /* украшательство */ } #right > div { display: none; /* контент панели изначально скрыт */ margin-top: 25px; /* украшательство */ padding: 15px; /* украшательство */ } /* ==================== КОНТЕНТ: слайдер ==================== */ #slider { width: 480px; /* ширина слайда + боковые отступы личных украшательств */ background: #ddd; /* украшательство */ border: #fff 10px solid; /* украшательство */ margin: 15px auto; /* украшательство */ padding: 15px; /* украшательство */ text-align: left; /* украшательство */ } /* контейнер набора слайдов */ #slider .elements { height: 240px; /* высота слайда (если низ не должен плавать) */ overflow: hidden; /* отсекаем выступившее за край */ position: relative; /* слайды позиционируем относительно контейнера */ background: #fff; /* украшательство */ margin: 15px 0; /* украшательство */ } /* контейнер отдельного слайда */ #slider .element { display: none; /* слайды изначально не видны */ height: 100%; /* слайды размером на всю клиентскую область */ width: 100%; /* слайды размером на всю клиентскую область */ position: absolute; /* слайды размещены один над другим */ padding: 15px; /* украшательство */ } /* ==================== КОНТЕНТ: сами слайды ==================== */ #slider .SlideBox1 { background: #f88; /* украшательство */ } #slider .SlideBox2 { background: #6cf; /* украшательство */ } #slider .SlideBox3 { background: #8f8; /* украшательство */ } #slider .SlideBox4 { background: #fc6; /* украшательство */ } /* ==================== КОНТЕНТ: строка состояния слайдера ==================== */ #slider .status { background: #bbb; /* украшательство */ color: #444; /* украшательство */ font-size: 8pt; /* украшательство */ line-height: 20px; /* украшательство */ margin-bottom: 15px; /* украшательство */ padding: 0 10px; /* украшательство */ } #slider .status span { color: #c4c; /* украшательство */ padding-right: 10px; /* украшательство */ } /* ==================== КОНТЕНТ: спойлер под слайдером ==================== */ #slider .more { display: none; /* контент спойлера изначально скрыт */ background: #eee; /* украшательство */ border: #bbb 1px solid; /* украшательство */ margin-top: 15px; /* украшательство */ padding: 15px; /* украшательство */ } /* ==================== КОНТЕНТ: уведомления по событию ==================== */ .cases { display: none; /* изначально скрыты */ } .cases.visible { display: block; /* такие изначально видны */ } .cases.visible.inline { /* возможно для каких-нибудь частей текста */ display: inline; } /* раскрасим текст уведомлений */ .NonSelected { color: #080; /* украшательство */ line-height: 20px; /* украшательство */ } /* ==================== НАВИГАТОРЫ: теневые флажки ==================== */ input[name^="shadow-"] { display: none; /* вообще не показываем */ } /* ==================== НАВИГАТОРЫ: флажок ==================== */ .checkbox { cursor: pointer; /* украшательство */ } /* ==================== ОБРАБОТКИ ОБЩИЕ: события флажка ==================== */ /* его общие события не отслеживаем */ /* ==================== НАВИГАТОРЫ: тумблер ==================== */ .switch { position: absolute; /* будем позиционировать как и панель */ right: 50%; /* двигаем на центр */ margin-right: 240px; /* отодвигаем влево за слайдер (половина его ширины) */ z-index: 1; /* чтобы оказался над панелью */ display: block; /* чтобы не терялась позиция от скрытия неблочных элементов */ cursor: pointer; /* украшательство */ margin-top: 15px; /* украшательство */ } .switch:after { content: '←'; /* украшательство */ background: #bbb; /* украшательство */ display: inline-block; /* украшательство */ font-size: 12pt; /* украшательство */ font-weight: bold; /* украшательство */ text-align: center; /* украшательство */ line-height: 25px; /* украшательство */ height: 25px; /* украшательство */ width: 25px; /* украшательство */ } .switch:hover:after { background: #8ff; /* украшательство */ } /* корректируем для правой панели */ .switch.RightKey1 { right: none; left: 50%; margin-right: 0; margin-left: 240px; } .switch.RightKey1:after { content: '→'; /* украшательство */ } /* ==================== ОБРАБОТКИ ОБЩИЕ: события тумблера ==================== */ /* включен */ input[name^="shadow-"]:checked + .switch:after { content: '→'; /* украшательство */ } /* включен (для правой панели) */ input[name^="shadow-"]:checked + .switch.RightKey1:after { content: '←'; /* украшательство */ } /* ==================== НАВИГАТОРЫ: переключатель ==================== */ .toggle { cursor: pointer; /* украшательство */ } .toggle:after { content: 'развернуть спойлер'; /* украшательство */ cursor: pointer; /* украшательство */ color: #08f; /* украшательство */ font-size: 8pt; /* украшательство */ text-decoration: underline; /* украшательство */ } .toggle:hover:after { text-decoration: none; /* украшательство */ } /* ==================== ОБРАБОТКИ ОБЩИЕ: события переключателя ==================== */ /* включен */ input[name^="shadow-"]:checked + .toggle:after { content: 'свернуть'; /* украшательство */ } /* ==================== НАВИГАТОРЫ: кнопка ==================== */ .button { cursor: pointer; /* украшательство */ background: #ccc; /* украшательство */ display: inline-block; /* украшательство */ text-align: center; /* украшательство */ margin: 0 5px 15px 5px; /* украшательство */ line-height: 30px; /* украшательство */ height: 30px; /* украшательство */ width: 80px; /* украшательство */ } /* ==================== ОБРАБОТКИ ОБЩИЕ: события кнопки ==================== */ /* курсор над кнопкой */ .button:hover { background: #8ff; /* украшательство */ } /* кнопка выбрана */ input[name^="shadow-"]:checked + .button { background: #f8f; /* украшательство */ } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события флажка 1 ==================== */ /* флажок помечен - скрываем связанные с ним уведомления */ input[name="function1"]:checked ~ .cases.visible.NonAutoDisplay, input[name="function1"]:checked ~ .cases .cases.visible.NonAutoDisplay, input[name="function1"]:checked ~ #slider .cases.visible.NonAutoDisplay, input[name="function1"]:checked ~ .cases.visible.inline.NonAutoDisplay, input[name="function1"]:checked ~ .cases .cases.visible.inline.NonAutoDisplay, input[name="function1"]:checked ~ #slider .cases.visible.inline.NonAutoDisplay { display: none !important; } /* и вдруг есть уведомление для противоположного состояния - надо показать */ input[name="function1"]:checked ~ .cases.inline.NonAutoDisplay, input[name="function1"]:checked ~ .cases .cases.inline.NonAutoDisplay, input[name="function1"]:checked ~ #slider .cases.inline.NonAutoDisplay { display: inline !important; } input[name="function1"]:checked ~ .cases.NonAutoDisplay, input[name="function1"]:checked ~ .cases .cases.NonAutoDisplay, input[name="function1"]:checked ~ #slider .cases.NonAutoDisplay { display: block; } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события слайдера ==================== */ /* курсор над кнопкой слайда - показываем её слайд (если флажок не включен) */ input[name="function1"]:not(:checked) ~ .SlideKey1:hover ~ #slider .elements .SlideBox1, input[name="function1"]:not(:checked) ~ .SlideKey2:hover ~ #slider .elements .SlideBox2, input[name="function1"]:not(:checked) ~ .SlideKey3:hover ~ #slider .elements .SlideBox3, input[name="function1"]:not(:checked) ~ .SlideKey4:hover ~ #slider .elements .SlideBox4 { display: block !important; /* гарантируем не перекрытие другим событием */ } /* и скрываем возможно выбранный слайд (ведь в z-index он может оказаться выше) */ input[name="function1"]:not(:checked) ~ .SlideKey1:hover ~ #slider .element, input[name="function1"]:not(:checked) ~ .SlideKey2:hover ~ #slider .element, input[name="function1"]:not(:checked) ~ .SlideKey3:hover ~ #slider .element, input[name="function1"]:not(:checked) ~ .SlideKey4:hover ~ #slider .element { display: none !important; /* гарантируем не перекрытие другим событием */ } /* кнопка слайда выбрана - показываем её слайд */ input[name^="shadow-"]:checked + .SlideKey1 ~ #slider .SlideBox1, input[name^="shadow-"]:checked + .SlideKey2 ~ #slider .SlideBox2, input[name^="shadow-"]:checked + .SlideKey3 ~ #slider .SlideBox3, input[name^="shadow-"]:checked + .SlideKey4 ~ #slider .SlideBox4 { display: block; } /* и скрываем связанное с этим уведомление */ input[name="shadow-slide"]:checked ~ .cases.visible.NonSelected, input[name="shadow-slide"]:checked ~ .cases .cases.visible.NonSelected, input[name="shadow-slide"]:checked ~ #slider .cases.visible.NonSelected, input[name="shadow-slide"]:checked ~ .cases.visible.inline.NonSelected, input[name="shadow-slide"]:checked ~ .cases .cases.visible.inline.NonSelected, input[name="shadow-slide"]:checked ~ #slider .cases.visible.inline.NonSelected { display: none !important; } /* и вдруг есть уведомление для противоположного состояния - надо показать */ input[name="shadow-slide"]:checked ~ .cases.inline.NonSelected, input[name="shadow-slide"]:checked ~ .cases .cases.inline.NonSelected, input[name="shadow-slide"]:checked ~ #slider .cases.inline.NonSelected { display: inline !important; } input[name="shadow-slide"]:checked ~ .cases.NonSelected, input[name="shadow-slide"]:checked ~ .cases .cases.NonSelected, input[name="shadow-slide"]:checked ~ #slider .cases.NonSelected { display: block; } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события спойлера 1 ==================== */ /* спойлер раскрыт - показываем контент спойлера */ input[name^="shadow-"]:checked + .SpoilerKey1 ~ .SpoilerBox1 { display: block !important; } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события спойлера 2 ==================== */ /* спойлер раскрыт - показываем контент спойлера */ input[name^="shadow-"]:checked + .SpoilerKey2 ~ .SpoilerBox2 { display: block !important; } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события левой панели ==================== */ /* панель раскрыта - выдвигаем */ input[name^="shadow-"]:checked + .LeftKey1 ~ .LeftBox1 { width: 100px !important; } /* и сдвигаем левее тумблер панели */ input[name^="shadow-"]:checked + .LeftKey1 { margin-right: 315px !important; } /* и показываем контент панели */ input[name^="shadow-"]:checked + .LeftKey1 ~ .LeftBox1 > div { display: block !important; } /* ==================== ОБРАБОТКИ ЧАСТНЫЕ: события правой панели ==================== */ /* панель раскрыта - выдвигаем */ input[name^="shadow-"]:checked + .RightKey1 ~ .RightBox1 { width: 100px !important; } /* и сдвигаем правее тумблер панели */ input[name^="shadow-"]:checked + .RightKey1 { margin-left: 315px !important; } /* и показываем контент панели */ input[name^="shadow-"]:checked + .RightKey1 ~ .RightBox1 > div { display: block !important; } /* ==================== ОТВЛЕЧЁННОЕ: подвал ==================== */ #powered { background: #bbb; color: #444; font-size: 8pt; margin: 30px 0 0 0; padding: 0 15px; line-height: 18pt; text-align: left; } #powered > a { color: #04f; text-decoration: none; white-space: nowrap; margin: 0 10px; } #powered > a:hover { text-decoration: underline; } #powered > #counters { height: 1px; width: 1px; overflow: hidden; opacity: 0.01; } #powered > #counters * { opacity: 0.01; } </style> <body> <!-- флажок 1 --> <input id="shadow-func1" name="function1" type="checkbox" /> <label class="checkbox Function1" for="shadow-func1" title="Также вносит изменения в строку состояния и текст уведомления под кнопками слайдов"> отключить показ слайдов по наведению курсора </label> <br /><br /> <!-- кнопки выбора слайдов --> <input id="shadow-slide1" name="shadow-slide" type="radio" /> <label class="button SlideKey1" for="shadow-slide1"> слайд 1 </label> <input id="shadow-slide2" name="shadow-slide" type="radio" /> <label class="button SlideKey2" for="shadow-slide2"> слайд 2 </label> <input id="shadow-slide3" name="shadow-slide" type="radio" /> <label class="button SlideKey3" for="shadow-slide3"> слайд 3 </label> <input id="shadow-slide4" name="shadow-slide" type="radio" /> <label class="button SlideKey4" for="shadow-slide4"> слайд 4 </label> <!-- уведомление по событию "Выбран / не выбран слайд" --> <div class="cases visible NonSelected"> <b> Кликните </b> <!-- уведомление по событию "Показ по клику" --> <u class="cases visible inline NonAutoDisplay" title="эта часть будет исчезать / появляться при переключении флажка">или наведите курсор</u> на кнопку нужного слайда, <br /> причём это уведомление исчезнет, как только нажмёте кнопку, <br /> а ниже появится ссылка, чтобы обновить страницу заново. </div> <!-- тумблер левой панели --> <input id="shadow-left1" name="shadow-left1" type="checkbox" /> <label class="switch LeftKey1" for="shadow-left1" title="Развернуть / свернуть панель"></label> <!-- левая выпадающая панель --> <div id="left" class="LeftBox1"> <div> здесь некий контент <b>для левой</b> панели </div> </div> <!-- тумблер правой панели --> <input id="shadow-right1" name="shadow-right1" type="checkbox" /> <label class="switch RightKey1" for="shadow-right1" title="Развернуть / свернуть панель"></label> <!-- правая выпадающая панель --> <div id="right" class="RightBox1"> <div> здесь некий контент <b>для правой</b> панели </div> </div> <!-- слайдер --> <div id="slider"> Пример слайдера, управляемого с помощью CSS3 <!-- сами слайды --> <div class="elements"> <div class="element SlideBox1"> СЛАЙД 1<br/><br /> или например <b>список товаров</b>, если бы это был модуль оформления заказа<br/><br /><br /> <a href="https://demo.imperacms.ru/cart?theme=IdealGift" target="_blank">здесь пример</a> работы такого модуля, только на JavaScript </div> <div class="element SlideBox2"> СЛАЙД 2<br/><br /> или например <b>ввод адреса доставки</b>, если бы это был модуль оформления заказа<br/><br /><br /> <a href="https://demo.imperacms.ru/cart?theme=IdealGift" target="_blank">здесь пример</a> работы такого модуля, только на JavaScript </div> <div class="element SlideBox3"> СЛАЙД 3<br/><br /> или например <b>выбор способа оплаты</b>, если бы это был модуль оформления заказа<br/><br /><br /> <a href="https://demo.imperacms.ru/cart?theme=IdealGift" target="_blank">здесь пример</a> работы такого модуля, только на JavaScript </div> <div class="element SlideBox4"> СЛАЙД 4<br/><br /> или например <b>завершение заказа</b>, если бы это был модуль оформления заказа<br/><br /><br /> <a href="https://demo.imperacms.ru/cart/?theme=IdealGift" target="_blank"> здесь пример </a> работы такого модуля, только на JavaScript </div> </div> <!-- строка состояния --> <div class="status"> <!-- уведомление по событию "Выбран / не выбран слайд" --> слайд: <span class="cases visible inline NonSelected">не выбран</span> <span class="cases inline NonSelected">выбран</span> <!-- уведомление по событию "Показ по клику" --> просмотр других: <span class="cases visible inline NonAutoDisplay">по наводке</span> <span class="cases inline NonAutoDisplay">по клику</span> </div> <!-- уведомление по событию "Выбран / не выбран слайд" --> <span class="cases inline NonSelected"> <a href="index.html">Открыть страницу заново</a>, чтобы ещё раз посмотреть смену уведомлений, связанных с событием "Выбор слайда".<br /><br /> </span> <b>Обратите внимание</b>, что: <!-- переключатель спойлера 1 --> <input id="shadow-spoiler1" name="shadow-spoiler1" type="checkbox" /> <label class="toggle SpoilerKey1" for="shadow-spoiler1"></label> <br /> <!-- контент спойлера 1 --> <div class="more SpoilerBox1"> - кнопки просмотра находятся вне DOM-ветки слайдера;<br /><br /> - нажатая кнопка остаётся подсвеченной;<br /><br /> - ненажатые кнопки демонстрируют свой слайд на время подвода курсора и возвращают показ прежнего выбранного слайда, если кнопку так и не нажали;<br /><br /> - данная функция отключается / включается флажком, размещенным над кнопками;<br /><br /> - слайдер удерживает показ выбранного слайда даже после отвода курсора от нажатой кнопки;<br /><br /> - строка состояния отображает текущие настройки;<br /><br /> - работоспособные спойлеры;<br /><br /> - выпадающие панели по бокам слайдера, а тумблеры панелей меняют свой вид (стрелки влево-вправо) согласно текущему состоянию панели. </div> <!-- текст после спойлера --> <br /> Вся эта логика работает <b>без использования JavaScript</b>, на одном лишь CSS3! С появлением CSS4 можно будет реализовать ещё больше при меньших ограничениях и упростить html-код.<br /><br /> Анимация смены слайдов и переключения уведомлений использована простейшая - показать / скрыть. В данном примере это не существенно. Но в принципе могла быть и более красивее, причём опять же средствами CSS (скажем нечто в духе <a href="https://daneden.me/animate/" target="_blank" rel="nofollow">animate.css</a>). <br /><br /> <b>Недостатки</b>, "навязанные" CSS3: <!-- переключатель спойлера 2 --> <input id="shadow-spoiler2" name="shadow-spoiler2" type="checkbox" /> <label class="toggle SpoilerKey2" for="shadow-spoiler2"></label> <br /> <!-- контент спойлера 2 --> <div class="more SpoilerBox2"> - особенности обобщенного родственного селектора (~) вынуждают располагать управляющий элемент в html-разметке ранее управляемой части контента;<br /><br /> - те же особенности селектора не дают размещать управляющий элемент в глубине другой DOM-ветки, чтобы он не имел прямого соседства с DOM-веткой управляемого контента;<br /><br /> - отсутствие селектора прямого родителя вынуждает выносить теневой флажок перед кнопкой в html-разметке и добавлять во флажок и кнопку лишние атрибуты, только чтобы указать их связанность, а также порождает лишние конструкции в стилях;<br /><br /> - проблема разрозненности теневого флажка и кнопки может быть решена и в CSS3 за счёт отказа от кнопки и превращения флажка в неё (более точно, кнопку подменит псевдо элемент :before или :after), однако не все браузеры поддерживают такое превращение, чтобы не примешивать туда свою "отсебятину". </div> </div> <!-- подвал --> </body> --> </html>