Как показать анимацию, скрытую за цветным div, используя «раскрывающий» div на поверхности

#html #css #mask #clip

#HTML #css

Вопрос:

Представьте, что у нас есть два слоя фона.

  • Нижний слой зеленый <div class="green"></div> . Для простоты давайте предположим, что это просто цвет. Но в моем проекте этот слой содержит анимацию css.
  • И поверх него идет еще один слой синего <div class="blue"></div> цвета .
  • Теперь я хочу иметь другой div , который идет поверх обоих, и он показывает зеленый фон (слой анимации в моем проекте).

Самый близкий пример, который я могу придумать, — это представить прожектор. Все кажется черным, а прожектор перемещается и показывает фон.

По сути, это то, что у меня есть:

 <div class="green">
    <div class="blue">
        <div class="reveal"></div>
    </div>
</div> 
 

Это будет выглядеть примерно так. Просто помните, что зеленый слой — это анимация в моем проекте.

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

ВОПРОС: как я могу дополнить .reveal стили для достижения вышеуказанного поведения.

  • Первый div — рисует .green фон (анимацию)
  • Второй фон dv — draws .blue идет поверх него
  • Третий / Четвертый /… divs — идет поверх обоих, но показывает все First div , что рисует фон

Примечание: первая и вторая обложки div 100% доступной ширины и высоты.

 .green {
    background-color: #159c82;
    width: 100vw;
    height: 100vh;
}

.blue {
    background-color: #1b4287;
    // I could change this to a sibling div and use,
    // position: absolute; but that seems unnecessary
    width: 100%;
    height: 100%;
}

.reveal {
    margin-top: 10px;
    margin-left: 10px;
    width: 200px;
    height: 50px;
    // not sure what else to put here to make it work
}

<div class="green">
    <div class="blue">
        <div class="reveal"></div>
    </div>
</div>
 

PS Я обнаружил один подход, который мне совсем не понравился.

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

Комментарии:

1. Могу ли я поместить <div class="reveal"> вне <div class="blue"> ?

2. в чем именно заключается ваш вопрос здесь?

3. @Dekel Я не уверен, как я могу завершить стили .reveal для достижения упомянутого поведения. Я отредактировал OP

4. @MARSHMALLOW Я думаю, да, пока у меня есть два полных слоя фона. Я планирую анимировать green фон в своем проекте.

5. @Dekel только что обновил

Ответ №1:

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

 .green {
  background: linear-gradient(45deg,#159c82,red);
  height: 100vh;
}

.blue {
  background:#1b4287;
  height: 100%;
  -webkit-mask:
    /* you adjust this */
    linear-gradient(#fff,#fff) 
     50px 50px/ /*left top*/
     200px 20px, /*width height*/
    /**/
    linear-gradient(#fff,#fff); 
  -webkit-mask-repeat:no-repeat;    
  -webkit-mask-composite: destination-out;
  
  mask:
    /* you adjust this */
    linear-gradient(#fff,#fff) 
     50px 50px/ /*left top*/
     200px 20px, /*width height*/
    /**/
    linear-gradient(#fff,#fff);
  mask-repeat:no-repeat;    
  mask-composite:exclude;
  transition:.5s;
}
.blue:hover {
  -webkit-mask-position:100px 100px,0 0;
          mask-position:100px 150px,0 0;
  -webkit-mask-size:300px 50px,auto;
          mask-size:300px 50px,auto;
}

body {
  margin: 0;
} 
 <div class="green">
  <div class="blue">
  </div>
</div> 

Вы также можете добавить столько масок, сколько захотите:

 .green {
  background: url(https://picsum.photos/id/1018/800/800) center/cover;
  height: 100vh;
}

.blue {
  background:#1b4287;
  height: 100%;
  -webkit-mask:
    /* 3rd mask */
    radial-gradient(farthest-side,#fff 99%,transparent) 
     top 50px right 50px/ 
     100px 100px,
    /**/
    /* 2nd mask */
    linear-gradient(#fff,#fff) 
     bottom 50px right 50px/ 
     300px 20px,
    /**/
    /* 1st mask */
    linear-gradient(#fff,#fff) 
     50px 50px/ 
     200px 20px,
    /**/
    linear-gradient(#fff,#fff);
  -webkit-mask-repeat:no-repeat;    
  -webkit-mask-composite: destination-out;
  
  mask:
    /* 3rd mask */
    radial-gradient(farthest-side,#fff 99%,transparent) 
     top 50px right 50px/ 
     100px 100px,
    /**/
    /* 2nd mask */
    linear-gradient(#fff,#fff) 
     bottom 50px right 50px/ 
     300px 20px,
    /**/
    /* 1st mask */
    linear-gradient(#fff,#fff) 
     50px 50px/ 
     200px 20px,
    /**/
    linear-gradient(#fff,#fff);
  mask-repeat:no-repeat;    
  mask-composite:exclude;
  transition:.5s;
}
.blue:hover {
  -webkit-mask-position:
            100px 100px,
            bottom 100px left 50px,
            top 50px right 50px,
            0 0;
          mask-position:
            100px 100px,
            bottom 100px left 50px,
            top 50px right 50px,
            0 0;
  -webkit-mask-size:
            150px 150px,
            50px 50px,
            300px 50px,
            auto;
          mask-size:
            150px 150px,
            50px 50px,
            300px 50px,
            auto;
}

body {
  margin: 0;
} 
 <div class="green">
  <div class="blue">
  </div>
</div> 

Ответ №2:

Технология, которая будет работать с еще более простым макетом, — это box-shadow

 .layer1 {
  width: 100%;
  height: 100%;
  position: absolute;
  background-image: linear-gradient(yellow, blue);
  background-size: 200% 200%;
  animation: bkg 2s infinite alternate;
  background-origin: padding-box;
}

.layer2 {
  width: 200px;
  height: 200px;
  position: absolute;
  background: transparent;
  border-radius: 30px;
  left: 20px;
  top: 40px;
  box-shadow: 0px 0px 0px 10000px blue;
}


@keyframes bkg {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 100% 100%
  }
} 
 <div class="layer1"></div>
<div class="layer2">
</div> 

Кроме того, у вас есть возможность добиться этого с помощью наложения.

Основным недостатком является то, что при этом используется жесткий свет, поэтому цвета, используемые в layer2, ограничены 0 или 255 для основных цветов (красный, синий и зеленый).

Это будет работать для чистого красного (255, 0,0), зеленого (0, 255, 0), синего (0, 0, 255), а также (255, 255, 0), (255, 0, 255), (0, 255, 255)

Но его преимущество в том, что вы можете настроить несколько divs для работы в качестве окон

 .layer1 {
  width: 100%;
  height: 100%;
  position: absolute;
  background-image: linear-gradient(yellow, blue);
  background-size: 200% 200%;
  animation: bkg 2s infinite alternate;
  background-origin: padding-box;
}

.layer2 {
  width: 100%;
  height: 100%;
  position: absolute;
  background: rgba(0, 255, 0);
  mix-blend-mode: hard-light;
}

.layer3 {
  width: 200px;
  height: 200px;
  position: absolute;
  background: grey;
  border-radius: 30px;
  left: 20px;
  top: 40px;
}

@keyframes bkg {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 100% 100%
  }
} 
 <div class="layer1"></div>
<div class="layer2">
  <div class="layer3"></div>
</div> 

Это будет работать также для нескольких divs:

 .layer1 {
  width: 100%;
  height: 100%;
  position: absolute;
  background-image: linear-gradient(yellow, blue);
  background-size: 200% 200%;
  animation: bkg 2s infinite alternate;
  background-origin: padding-box;
}

.layer2 {
  width: 100%;
  height: 100%;
  position: absolute;
  background: rgba(0, 255, 0);
  mix-blend-mode: hard-light;
}

.layer3 {
  width: 200px;
  height: 200px;
  position: absolute;
  background: grey;
  border-radius: 30px;
  left: 20px;
  top: 40px;
}

.layer3:nth-child(2) {
  left: 120px;
  top: 80px;
}

@keyframes bkg {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 100% 100%
  }
} 
 <div class="layer1"></div>
<div class="layer2">
  <div class="layer3"></div>
  <div class="layer3"></div>
</div> 

Ответ №3:

Вы хотите поместить раскрывающий div только в эту позицию или показать зеленый цвет с нижнего слоя?

только для позиции вы можете добавить реальное положение в свой синий div и абсолютное положение в вашем раскрывающем div со значениями top и left.

 .green {
    background-color: #159c82;
    width: 100vw;
    height: 100vh;
}

.blue {
    background-color: #1b4287;
    width: 100%;
    height: 100%;

    position: relative;
}

.reveal {
    position: absolute;
    top: 10px;
    left: 10px;

    width: 200px;
    height: 50px;
}
 

Комментарии:

1. Это не то, что я ищу, .reveal нужно показать, какой бы ни был нижний фон. Я обновил вопрос, надеюсь, это имеет больше смысла.

2. Я хочу показать зеленый цвет с нижнего слоя.

Ответ №4:

Если я вас правильно понял, вам, вероятно, следует использовать переменную css. https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties

Редактируя ваш пример, мы получаем следующее.

 :root {
  --bottom-layer-color: #159c82
}

.green {
  background-color: var(--bottom-layer-color);
  width: 100vw;
  height: 100vh;
}

.blue {
  background-color: #1b4287;
  width: 100%;
  height: 100%;
}

.reveal {
  margin-top: 10px;
  margin-left: 10px;
  width: 200px;
  height: 50px;
  background-color: var(--bottom-layer-color)
}

<div class="green">
  <div class="blue">
    <div class="reveal"></div>
  </div>
</div>
 

приветствия,

чтобы изменить цвет с помощью css:

 /* Use a later css file to redeclare the root variable,    */
/* this will override previously declared css. */
/* https://css-tricks.com/precedence-css-order-css-matters/ */
:root {
  --bottom-layer-color: powderblue
}
 

чтобы изменить цвет с помощью javascript:

 const eStyle = document.documentElement.style
eStyle.setProperty('--top-bar-height', '263px');
 

Вы можете многое изменить с помощью переменных css. Не только цвета фона.

Например

 root: {
  --bottom-layer-color: #159c82
  --bottom-layer-radius: 50%;
  /* this would make the bottom layer a circle. And reaveal a circle. */
}

.green {
  background-color: var(--bottom-layer-color)
  border-radius: var(--bottom-layer-color)
  width: 100vw;
  height: 100vh;
}

.reveal {
  background-color: var(--bottom-layer-color)
  border-radius: var(--bottom-layer-color)
}

/* Set --bottom-layer-radius back to 0 to make both items square again. */
 

Комментарии:

1. Нет, это не сработает для меня. У меня есть анимация на нижнем слое. Итак, это должно быть точно таким, каким является нижний слой.

Ответ №5:

Это одна из самых простых вещей, которые можно сделать в CSS

 <Style>
.blue {
width: 100%;
height: 300px;
background-color: lightblue;
}
</style>
<div class="blue">
</div>