Gooey CSS Effects with Contrast Parent

Gooey css effects with contrast parent

I have taken your effect. On the container, I have set a pseudo element that covers it, with whatever color you want.

And with a mix-blend-mode, I can set this color where the container is black, keeping the remaining white:

(By the way, a very nice effect !)

body{  background: #fff;}
.blobs { position:absolute; top:0; left:0; bottom:0; right:0; background: #fff; width:400px; height:200px; margin:auto; filter:contrast(20); -webkit-filter:contrast(20);}
.blobs:after { content: ""; position: absolute; top:0; left:0; bottom:0; right:0; background-color: coral; mix-blend-mode: lighten;}
.blob { background:black; width:100px; height:100px; position:absolute; left:50%; top:50%; margin-top:-50px; margin-left:-50px; border-radius:100%; transition: cubic-bezier(0.82, 0.1, 0.24, 0.99) 1.5s; box-shadow: 0 0 30px 10px black;}
.blobs:hover .blob:first-child { transform:translateX(-70px);}
.blobs:hover .blob:last-child { transform:translateX(70px);}
<div class="blobs">  <div class="blob"></div>  <div class="blob"></div></div>

CSS Filter blur and contrast for gooey effect

This is how it can be done with: filter: blur(10px) contrast(30);. You need to add background:white; to the container. Also you'll need some extra space between the limit of the container and the circles so I've added padding:100px;

body {  width: 100vw; height: 100vh;  display: grid;  place-items: center;}.container {  display: flex;  flex-direction: column;  background:white;  padding:100px;  filter: blur(15px) contrast(30);  }
.circle { width: 100px; height: 100px; background-color: red; /* border-radius: 100%;*/}
.circle-1 { border-radius: 50%; /* top: 50px; border: 5px solid black;*/ transform: translateY(20px);}.circle-2 { border-radius: 95% 5% 70% 30% / 52% 30% 70% 48% ; transform: rotateY(-180deg);}
<div class="container">  <div class="circle circle-1"></div><div class="circle circle-2"></div></div>

Why is this css gooey not working?

"Gooey" filters are handled via SVG filters which you can hook into with CSS by referencing their ID as filter: url(#filter-ID);

For your example this can be solved by including the SVG filter reference in the HTML:

<svg>
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
</svg>

For more information on how the color matrices interact with the blur filter there's a brilliant write up on the gooey effect here: https://css-tricks.com/gooey-effect/

Here's a working example based on your own: http://codepen.io/anon/pen/KaeVJM

Why does applying a CSS-Filter on the parent break the child positioning?

If we refer to the specification we can read:

A value other than none for the filter property results in the
creation of a containing block for absolute and fixed positioned
descendants unless the element it applies to is a document root
element in the current browsing context. The list of functions are
applied in the order provided.

This means that your position:fixed element will be positioned relatively to the filtered container and no more the viewport. In other words, it's still fixed but inside its new containing block (the filtered container)

Here is a simplified version to illustrate the issue:

.container {
display: inline-block;
width: 200px;
height: 200vh;
border: 1px solid;
}

.container>div {
position: fixed;
width: 100px;
height: 100px;
background: red;
color: #fff;
}
<div class="container">
<div>I am fixed on scroll</div>
</div>

<div class="container" style="filter:grayscale(1);">
<div>I move with the scroll</div>
</div>

What happens when nesting elements with position: fixed inside each other?

The fixing and the positioning are two separate things. They're positioned the same as absolutely positioned elements: relative to their containing block. But in contrast with absolutely positioned elements, they remain fixed to that position with respect to the viewport (i.e. they don't move when scrolling):

http://www.w3.org/TR/CSS2/visuren.html#propdef-position

The box's position is calculated according to the 'absolute' model, but in addition, the box is fixed with respect to some reference.

Positioning

The definition of containing block says:

If the element has 'position: fixed', the containing block is established by the viewport in the case of continuous media (...)

and

If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed' (...)

which suggests that while their positioning algorithm is the same (they're both positioned relative to their containing block), the containing block for fixed elements is always the viewport, in contrast with absolutely positioned elements, so they should be positioned relative to that and not to any absolutely or fixed-positioned elements.

And as a matter of fact, that is indeed the case. For example, if you add top: 20px to .fixed, both divs will be positioned 20 pixels from the top of the viewport. The nested fixed div does not get positioned 20 pixels down from the top of its parent.

The reason you're not seeing that in this case is because you're not actually setting any of the left/top/right/bottom properties, so their positions are determined by the position they would have in the flow (their "static position"), which as my first quote said, is done according to the absolute model.



Related Topics



Leave a reply



Submit