#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
для достижения упомянутого поведения. Я отредактировал OP4. @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>