@popov654
Специалист в области веб-технологий

Странности с CSS и слоями — почему так происходит?

Добрый день,

Я пытаюсь создать небольшой слайдер (это учебный пример для моей будущей книжки по HTML/CSS/JS).
Всё было нормально, но в некоторый момент началось странное поведение в плане перекрытия блоков, которое я никак не могу понять. Возможно, ответ лежит где-то в недрах стандарта? Огромная просьба подсказать, в чём проблема, или хотя бы где почитать, чтобы понять это.

Итак, есть следующая разметка:

<div id="main">
      <header><div id="logo"></div></header>
      <nav><a href="/" class="current">Главная</a><a href="tours.html">Туры</a><a href="feedback.html">Отзывы</a><a href="about.html">О нас</a></nav>
      <main>
          <p>Добро пожаловать на сайт туроператора "Компас-Тур"!</p>
          <div id="slider_wrap">
              <div id="slider"><div class="left"></div><div class="right"></div><div class="film"></div></div>
              <div class="dots"></div>
          </div>
      </main>
      <footer></footer>
</div>


...

   main {
      min-height: 530px;
      padding: 32px 28px 18px;
      font-family: Arial;
      font-size: 13px;
   }
   main > h1 {
      font-family: Georgia;
      color: #c50;
      font-size: 24px;
      margin: 14px 0px 18px;
   }
   footer {
      height: 38px;
   }
   #slider_wrap {
       width: 510px;
   }
   #slider {
      width: 510px;
      height: 290px;
      position: relative;
      overflow: hidden;
      margin-top: 18px;
   }
   #slider .film {
      position: absolute;
      top: 0px;
      left: 0px;
      height: 100%;
      transition: left 1s;
      -moz-tranzition: left 1s;
      -o-transition: left 1s;
      -ms-transition: left 1s;
   }
   #slider .film > a {
      display: block;
      text-decoration: none;
      border: none;
      float: left;
      width: 510px;
      height: 290px;
      position: relative;
   }
   #slider .film > a > .title {
      position: absolute;
      left: 0px;
      bottom: 0px;
      width: 120px;
      height: 32px;
      background: rgba(0, 0, 0, 0.6);
      padding: 4px 16px;
      transition: opacity 0.8s ease-in-out 0.2s;
   }
   #slider .film > a > .title > span {
      color: #fff;
      font-size: 20px;
      font-family: Verdana;
      text-shadow: 1px 0px #000;
   }
   #slider_wrap > .dots {
       margin: -26px auto 0px;
       width: 160px;
       text-align: center;
       z-index: 1;
       position: relative;
   }
   #slider_wrap > .dots > div {
       display: inline-block;
       width: 16px;
       height: 16px;
       margin: 2px;
   }
   #slider_wrap > .dots > div > div {
       display: inline-block;
       border: 2px solid #fff;
       border-radius: 6px;
       width: 8px;
       height: 8px;
       margin: 0px 2px;

   }
   #slider_wrap > .dots > div.active > div {
       background: #fff;
   }


Она даёт следующий вывод:

5b51b238a9096236813139.png

Не буду полностью приводить все стили и скрипты, просто объясню, что происходит, и что меня не устраивает.

Изначально в элементе с классом "dots" выводились элементы, которые служили индикаторами текущей страницы слайдера. Выводились они как инлайново-блочные элементы, содержимое центрировалось через text-align. Затем я сделал их кликабельными. Потом я увидел, что кликать по ним не очень-то удобно из-за небольшого размера, и решил обернуть их в обёртки, дабы сделать допустимую область для клика чуть больше. И вот тут начались проблемы.

Дело в том, что изначально я ради гибкости (чтобы была возможность отображать эти индикаторы и вне слайдера) не стал вкладывать элемент с классом "dots" прямо в слайдер, а вложил его в специальный элемент-обёртку. Потом я всё же решил выводить его поверх слайдера, и использовал сдвиг с помощью margin-top в верхнюю сторону.

Вопрос: почему до того, как я использовал обёртки у div-ов внутри элемента "dots" элемент "dots" выводился поверх слайдера, а как только я ввёл их - слайдер начал его перекрывать, и потребовались довольно нетривиальные операции с z-index, чтобы это поправить?

Два рабочих варианта изменений, которые я нашёл: добавить элементу c class="dots" position: relative (то есть вытащить его из нормального потока); добавить элементу c id="main" свойства z-index: -1; position: relative, а элементу с id="slider" z-index: -1 (position: relative у него уже есть, так как id="film" внутри него позиционируется абсолютно).

Вопрос 2: Я полагал, что при использовании отрицательных z-index сначала выводятся элементы с отрицательными индексами в порядке их возрастания, затем фон, затем элементы с position: static, затем элементы с нулевыми и положительными индексами. Я так думал потому, что мне удалось в тестовом примере вывести элемент под фоном, присвоив ему z-index, равный -1 (фон был полупрозрачный).

Но теперь, произведя все манипуляции, которые потребовались, чтобы пофиксить проблему, эта теория рушится: если я присваиваю элементу "slider" z-index, равный -1, то он выводится... под фоном элемента "main" (даже если задать элементу "slider_wrap" свой собственный фон)! Почему происходит именно так? При создании элемента с z-index меньше нуля, он проваливается не только под фон своего родителя, но и под фоны всех предков (на самом деле, не совсем всех, фон элемента body остался ниже элемента "slider").

UPD: со второй частью вопроса частично прояснилось. Если добавить элементу с id="slider_wrap" position: relative; z-index: 0, а элементу с id="slider" присвоить z-index, равный -1, то оно тоже отображается правильно. При чём если выкинуть z-index: 0, то всё снова ломается. И это логично - ведь указывая z-index на этом элементе, я создаю новый контекст наложения, в противном же случае этот контекст находится выше, видимо как раз на элементе с id="main" (правда я хз, почему именно на нём - там не указан z-index, и тот элемент даже не позиционируемый).
  • Вопрос задан
  • 152 просмотра
Пригласить эксперта
Ответы на вопрос 1
webinar
@webinar
Учим yii: https://youtu.be/-WRMlGHLgRg
Думаю тут прикол с прозрачностью, как бы странно это не звучало, вот пример:
https://codepen.io/wokster/pen/OwbYrK
поробуйте убрать 1-е css привило
div:first-child {
  opacity: .99; 
}

Казалось бы opacity, а нет. Вот разъяснение:
https://habr.com/post/166435/
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы