Цветок парадокса z-index в CSS

98

Я хотел бы создать парадоксальный эффект с помощью свойства z-index CSS .

В моем коде есть пять кругов, как на изображении ниже, и все они абсолютно позиционированы без определения z-index. Поэтому по умолчанию каждый кружок перекрывает предыдущий.

Прямо сейчас круг 5 перекрывает круг 1 (левое изображение). Парадокс, которого я хотел бы достичь, заключается в том, чтобы в то же время кружок 1 находился под кружком 2 и над кружком 5 (как на правом изображении).


(источник: schramek.cz )

Вот мой код

Разметка:

<div class="item i1">1</div>
<div class="item i2">2</div>
<div class="item i3">3</div>
<div class="item i4">4</div> 
<div class="item i5">5</div>

CSS

.item {
    width: 50px;
    height: 50px;
    line-height: 50px;
    border: 1px solid red;
    background: silver;
    border-radius: 50%;
    text-align: center;
}

.i1 { position: absolute; top: 30px; left: 0px; }
.i2 { position: absolute; top: 0px; left: 35px; }
.i3 { position: absolute; top: 30px; left: 65px; }
.i4 { position: absolute; top: 70px; left: 50px; }
.i5 { position: absolute; top: 70px; left: 15px; }

Живой пример также доступен на http://jsfiddle.net/Kx2k5/ .

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

1ubos
источник
10
Если это просто проблема кодирования, может быть, это принадлежит codegolf?
TylerH
12
Я думаю, ОП ищет помощи. Он хочет, чтобы решить эту проблему было для него проблемой. Я думаю, что это то, чему многие научатся, когда сделают это. Я, например, считаю эту технику полезной.
LOTUSMS
@ 1ubos. Никакого jquery / JS? Мне кажется, что потребуется какое-то логическое использование IndexOf
LOTUSMS
5
это невозможно при использовании z-index. z-index определяет слои, это последовательность целых чисел: -x, 0, x вы не можете иметь: x1 <x2 <x1
gondo
4
Пожалуйста, не обходите фильтр качества с помощью поддельного блока кода. Либо включите код в сам вопрос, либо удалите ссылку на скрипт, если она не важна. Кроме того, я бы посоветовал вам перефразировать это как реальную проблему с исследованием, а не ЗАДАЧУ, если вы хотите, чтобы к вашему вопросу отнеслись серьезно.
BoltClock

Ответы:

91

Вот моя попытка: http://jsfiddle.net/Kx2k5/1/
(успешно протестирован на Fx27, Ch33, IE9, Sf5.1.10и Op19)


CSS

.item {
   /* include borders on width and height */  
   -webkit-box-sizing : border-box;
   -moz-box-sizing    : border-box;
   box-sizing         : border-box;
   ...
}

.i1:after {
   content: "";

   /* overlap a circle over circle #1 */
   position : absolute;
   z-index  : 1;
   top      : 0;
   left     : 0;
   height   : 100%;
   width    : 100%;

   /* inherit border, background and border-radius */
   background    : inherit;
   border-bottom : inherit;
   border-radius : inherit;

   /* only show the bottom area of the pseudoelement */
   clip          : rect(35px 50px 50px 0);
}

В основном я перекрыл :afterпсевдоэлемент над первым кругом (с некоторыми унаследованными свойствами), затем я обрезал его с помощью clip()свойства, поэтому я делаю видимым только его нижнюю часть (где круг#1 перекрывает круг#5 ).

Для свойств CSS , которые я использовал здесь, этот пример должен работать даже на IE8 ( box-sizing, clip(), inherit, и pseudoelements поддерживается там)


Скриншот полученного эффекта

введите описание изображения здесь

Фабрицио Кальдеран
источник
2
Похоже, я пришла на вечеринку слишком поздно! Хорошая работа! : P
Ruddy
2
Я не только выучил немного CSS сегодня, но и немного
освежил
29

Моя попытка также использовать clip. Идея заключалась в том, чтобы получить половину и половину div. Таким образом установкаz-index будет работать.

Таким образом, вы можете установить верхнюю часть, z-index: -1а нижнюю -z-index: 1 .

Итог:

введите описание изображения здесь

.item {
  width: 50px;
  height: 50px;
  line-height: 50px;
  border: 1px solid red;
  background: silver;
  border-radius: 50%;
  text-align: center;
}
.under {
  z-index: -1;
}
.above {
  z-index: 1;
  overflow: hidden;
  clip: rect(30px 50px 60px 0);
}
.i1 {
  position: absolute;
  top: 30px;
  left: 0px;
}
.i2 {
  position: absolute;
  top: 0px;
  left: 35px;
}
.i3 {
  position: absolute;
  top: 30px;
  left: 65px;
}
.i4 {
  position: absolute;
  top: 70px;
  left: 50px;
}
.i5 {
  position: absolute;
  top: 70px;
  left: 15px;
}
<div class="item i1 under">1</div>
<div class="item i1 above">1</div>
<div class="item i2">2</div>
<div class="item i3">3</div>
<div class="item i4">4</div>
<div class="item i5">5</div>

ДЕМО ЗДЕСЬ

Примечание. Протестировано в IE 10+, FF 26+, Chrome 33+ и Safari 5.1.7+.

Рудди
источник
любые идеи с этим вопросом: stackoverflow.com/questions/22377416/how-to-warp-image#22377416
NoobEditor
18

Вот моя попытка.

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

Демо

CSS (отличается от начальной точки)

.i1 { 
  position: absolute; top: 30px; left: 0px;
  &:before {
    content: '';
    position: absolute;
    z-index: 100;
    top: 0;
    left: 0;
    width: 50px;
    height: 50px;
    border-radius:  50%;
    box-shadow: inset 5px -5px 0 6px silver;
    border-bottom: solid 1px red;
  }
}

Конечный продукт введите описание изображения здесь

DMTintner
источник
Хороший ответ! Единственная проблема, о которой я могу подумать, - это то, что тени не поддерживаются IE 8 и ниже. Псевдоэлементы в любом случае не поддерживаются IE 7 и более ранними версиями :)
The Pragmatick
4

К сожалению, это всего лишь теоретический ответ, так как по какой-то причине я не могу приступить -webkit-transform-style: preserve-3d;к работе (должно быть, совершаю очевидную ошибку, но, похоже, не могу ее понять). В любом случае, прочитав ваш вопрос, я, как и всякий парадокс, задался вопросом, почему это всего лишь кажущаяся невозможность, а не реальная. Еще через несколько секунд я понимаю, что в реальной жизни листья немного поворачиваются, что позволяет такой вещи существовать. Итак, я хотел придумать простую демонстрацию этой техники, но без предыдущего свойства это невозможно (оно переносится на плоский родительский слой). В любом случае, вот базовый код, тем не менее

<div class="container">
    <div>
        <div class="i1 leaf">
            <div class="item">1</div>
        </div>
        <div class="i2 leaf">
            <div class="item">2</div>
        </div>
        <div class="i3 leaf">
            <div class="item">3</div>
        </div>
        <div class="i4 leaf">
            <div class="item">4</div>
        </div>
        <div class="i5 leaf">
            <div class="item">5</div>
        </div>
    </div>
</div>

И css:

.i1 {
    -webkit-transform:rotateZ(288deg)
}
.i2 {
    -webkit-transform:rotateZ(0deg)
}
.i3 {
    -webkit-transform:rotateZ(72deg)
}
.i4 {
    -webkit-transform:rotateZ(144deg)
}
.i5 {
    -webkit-transform:rotateZ(216deg)
}
.leaf { 
    position:absolute;
    left:35px;
    top:35px;
}
.leaf > .item {
    -webkit-transform:rotateY(30deg) translateY(35px)
}

И вы можете найти полный код здесь .

Дэвид Малдер
источник
У меня работает в Safari 7.0.2; может это твой браузер? - РЕДАКТИРОВАТЬ - махехе, preserve-3d действительно не работает. В любом случае разумное 3D-изображение :)
tomsmeding
2

JS Fiddle

HTML

<div class="item i1">1</div>
<div class="item i2">2</div>
<div class="item i3">3</div>
<div class="item i4">4</div>
<div id="five">5</div>
<div class="item2 i5"></div>
<div class="item3 i6"></div>

CSS

.item {
    width: 50px;
    height: 50px;
    line-height: 50px;
    border: 1px solid red;
    background: silver;
    border-radius: 50%;
    text-align: center;
}
.item2 {
      width: 25px;
    height: 50px;
    line-height: 50px;
    border: 1px solid red;
    border-right: none;
    border-radius: 50px 0 0 50px;
    background: silver 50%;
    background-size: 25px;
    text-align: center;   
        z-index: -3;
}
.item3 {
    width: 25px;
    height: 50px;
    line-height: 50px;
    border: 1px solid red;
    border-left: none;
    border-radius: 0 50px 50px 0;
    background: silver 50%;
    background-size: 25px;
    text-align: center;    
}
.i1 {
    position: absolute;
    top: 30px;
    left: 0px;
}
.i2 {
    position: absolute;
    top: 0px;
    left: 35px;
}
.i3 {
    position: absolute;
    top: 30px;
    left: 65px;
}
.i4 {
    position: absolute;
    top: 70px;
    left: 55px;
}
.i5 {
    position: absolute;
    top: 70px;
    left: 15px;
}
.i5 {
    position: absolute;
    top: 72px;
    left:19px;

}
.i6 {
    position: absolute;
    top: 72px;
    left: 44px;
}
#five {
     position: absolute;
    top: 88px;
    left: 40px;
    z-index: 100;
}
История Дерека
источник
Вы могли бы немного сократить свой код, удалив лишние элементы в item2и item3. А также переехал position: absoluteв .ixи #fiveв item, item2иitem3
webprogrammer
0

Живая демонстрация JS Fiddle

Работает и на IE8.

HTML

<div class="half under"><div class="item i1">1</div></div>
<div class="half above"><div class="item i1">1</div></div>
<div class="item i2">2</div>
<div class="item i3">3</div>
<div class="item i4">4</div> 
<div class="item i5">5</div>

CSS

.item {
    width: 50px;
    height: 50px;
    line-height: 50px;
    border: 1px solid red;
    background: silver;
    border-radius: 50%;
    text-align: center;
}
.half {
    position: absolute;
    overflow: hidden;
    width: 52px;
    height: 26px;
    line-height: 52px;
    text-align: center;
}
.half.under {
    top: 30px; 
    left: 0px;
    z-index: -1;
    border-radius: 90px 90px 0 0;
}
.half.above {
    top: 55px;
    left: 0px;
    z-index: 1;
    border-radius: 0 0 90px 90px;
}
.half.above .i1 { margin-top:-50%; }
.i2 { position: absolute; top: 0px; left: 35px;}
.i3 { position: absolute; top: 30px; left: 65px;}
.i4 { position: absolute; top: 70px; left: 50px; }
.i5 { position: absolute; top: 70px; left: 15px; }
Мартин Урбан
источник