ground filter blur transition issue - css

Pressing the button blurs the background, but while transitioning, the edges of the div do not transition well. This problem exists in all browsers except firefox how can i fix it?
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
div.classList.toggle('blur');
});
body {
margin: 0;
background: url('https://images.pexels.com/photos/2763927/pexels-photo-2763927.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1')no-repeat;
background-size: cover;
}
div {
width: 900px;
height: 900px;
transition: 1s ease;
}
.blur {
backdrop-filter: blur(20px);
transition: 1s ease;
}
<body>
<div class="cube"></div>
<button>BLUR BUTTON</button>
</body>

Because the image fills <body>, but the .blur is in the <div>, which is only 900x900 pixels.
Quick fix:
Change: var div = document.querySelector('div');
to: var div = document.body;
Or: move the background: url(..); background-size: .. to the div and take it from there.
var btn = document.querySelector('button');
var div = document.body;
btn.addEventListener('click', function() {
div.classList.toggle('blur');
});
body {
margin: 0;
background: url('https://images.pexels.com/photos/2763927/pexels-photo-2763927.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1')no-repeat;
background-size: cover;
}
div {
width: 900px;
height: 900px;
transition: 1s ease;
}
.blur {
backdrop-filter: blur(20px);
transition: 1s ease;
}
<body>
<div class="cube"></div>
<button>BLUR BUTTON</button>
</body>

Related

CSS - How to reverse the Animation on removal

I have a page in my website where I display to panels, side by side. I'm displaying these 2 panels in 2 views: Horizontal and Vertical. I have a button that switches between these 2 views. I'm trying to add some CSS animation on the transition between the two views. However my animation work only in one direction (from Vertical to Horizontal), the reverse animation appear in the wrong order.
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: width, height;
-webkit-transition-duration: 2s, 2s;
-webkit-transition-delay: 0s, 2s;
-webkit-transition-timing-function: ease;
display: inline-block;
width: 50%;
height: 100%;
}
.vertical-box
{
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: height, width; /* swapped */
-webkit-transition-duration: 0.5s, 0.5s;
-webkit-transition-delay: 0s, 0.5s;
-webkit-transition-timing-function: ease;
display: block; /* TRY THIS */
float: left; /* AND THIS */
width: 50%;
height: 100%;
}
.vertical-box
{
-webkit-transition-property: width, height; /* added */
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
Explained
Added transition-property: width, height; to .vertical-box
Desired behavior: expand width, shink height; expand height shrink width.
.box has transition-property first height then width
.vertical-box overwrites and flippes transition-property: first width, then height
You might think this is the wrong order, but as soon as you click the class is applied immideately, but the transition takes time. So you transition from .box to .vertical-box with the transition-property of .vertical-box and vise versa.
EDIT Answer using animation (little hacky, since i found no way to reset current keyframe)
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.removeClass("vertical-box-reverse");
window.requestAnimationFrame(function() { // apply to forget animation state
window.requestAnimationFrame(function() { // re-apply animation
boxes.addClass("vertical-box");
});
});
}
else
{
boxes.removeClass("vertical-box");
window.requestAnimationFrame(function() { // apply to forget animation state
boxes.addClass("vertical-box-before-reverse"); // apply to set animation end-like state
window.requestAnimationFrame(function() { // re-apply animation
boxes.removeClass("vertical-box-before-reverse");
boxes.addClass("vertical-box-reverse");
});
});
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
display: block;
float: left;
width: 50%;
height: 100%;
}
.a.vertical-box { animation: boxAnimationA 1s normal forwards; }
.b.vertical-box { animation: boxAnimationB 1s normal forwards; }
.a.vertical-box-reverse { animation: boxAnimationA 1s ease-in reverse forwards; }
.b.vertical-box-reverse { animation: boxAnimationB 1s ease-in reverse forwards; }
.vertical-box-before-reverse { width: 100%; height: 50%; }
.a { background-color: darkred; }
.b { background-color: darkorchid; }
/* Keyframes */
#keyframes boxAnimationA {
0% { width: 50%; }
50% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
#keyframes boxAnimationB {
0% { width: 50%; }
50% { width: 0%; height: 100%; }
51% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>

How can I add two transition transforms but one after one?

I want to add 2 transition transforms
But I want to start the second transform after the end of the first transform
the element should go to a point slowly and after that it should go to another point
transform: translate(0%, 300%), translate(15%, -136%);
You cannot do this with just a single element using transition because when you put more than one translate within the transform, the transform property on the whole is transitioned and not one by one.
With pure CSS transition using an extra wrapper element:
If you add an extra wrapper element around the actual element and put one of the transforms on the wrapper element you could achieve the effect that you are looking for. It would also produce the exact reverse effect on the hover out (hover the body and hover out in the below snippet).
.wrapper {
position: relative;
height: 100px;
width: 100px;
transition: all 1s 1s;
}
.content {
position: absolute;
height: 100%;
width: 100%;
border: 1px solid;
transition: all 1s;
}
body:hover .content {
transform: translate(15%, -136%);
transition: all 1s 1s;
}
body:hover > .wrapper {
transform: translate(0%, 300%);
transition: all 1s;
}
body {
min-height: 100vh;
}
<div class='wrapper'>
<div class='content'>Some text</div>
</div>
Transition with a bit of JS/jQuery without any extra elements:
If you add an extra wrapper element around the actual element and put one of the transforms on the wrapper element you could achieve the effect that you are looking for. It would also produce the exact reverse effect on the hover out (hover the body and hover out in the below snippet).
$(document).ready(function() {
var isHover; /* variable to track state */
$('body').hover(function() {
isHover = !isHover; /* invert the state */
$('.content').css('transform', 'translate(0%, 300%)');
}, function() {
isHover = !isHover; /* invert the state */
$('.content').css('transform', 'translate(0%, 300%)');
});
$('.content').on('transitionend', function() {
if (isHover) {
$('.content').css('transform', 'translate(0%, 300%) translate(15%, -136%)');
} else {
$('.content').css('transform', 'none');
}
});
});
.content {
height: 100px;
width: 100px;
border: 1px solid;
transition: all 1s;
}
body {
min-height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='content'>Some text</div>
With animation and no extra element:
Using animations this can be done using a single element but the reverse effect is tough to achieve. We would have to write extra code for this and even then it will be complex.
.content {
position: relative;
height: 100px;
width: 100px;
border: 1px solid;
}
body:hover > .content {
animation: move 1s forwards;
}
#keyframes move {
0% {
transform: none;
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: translate(0%, 300%) translate(15%, -136%);
}
}
body {
min-height: 100vh;
}
<div class='content'>Some text</div>
Animations with reverse effect:
Below is a snippet which produces the reverse effect also using CSS animations. But as you can see it is a bit complex. We can do this using a single animation also but it would become more complex.
$(document).ready(function() {
$('body').hover(function() {
$('.content').css('transform', 'none');
$('.content').removeClass('hover-out').addClass('hover-in');
}, function() {
$('.content').css('transform', 'translate(0%, 300%) translate(15%, -136%)'); /* as soon as an animation is removed, the element would snap back to original state, to avoid that we have to add final state via inline style */
$('.content').removeClass('hover-in').addClass('hover-out');
});
});
.content {
height: 100px;
width: 100px;
border: 1px solid;
}
.hover-in {
animation: hover-in 1s forwards;
}
.hover-out {
animation: hover-out 1s forwards;
}
#keyframes hover-in {
0% {
transform: none;
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: translate(0%, 300%) translate(15%, -136%);
}
}
#keyframes hover-out {
0% {
transform: translate(0%, 300%) translate(15%, -136%);
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: none;
}
}
body {
min-height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='content'>Some text</div>

CSS rgba background color loading before opacity

I have an image taking up the whole viewport. Over top of it is a div, also taking up the whole viewport. The div has background: rgba(0,0,0,.5); to make the image behind it look darker. It works great, except that when the page is loading, the whole screen is covered with gray before opacity is applied and I can see the image underneath.
Is there any way to make the image and the div (with opacity applied) appear at the same time? I don't want to see the big block of gray while the page is loading.
This should do it for you https://jsfiddle.net/c259LrpL/26/
This will wait till images are loaded then make the img and the div visible at the same time... I think
<img id="img1" src="http://lorempixel.com/1200/1200/sports/1/" style="visibility: hidden" >
<div id="over" style="visibility: hidden" >
</div>
<script>
$(window).on("load", function() {
$("#img1").css("visibility", "visible");
$("#over").css("visibility", "visible");
});
</script>
Consider this idea. We'll use the :after pseudoclass of the <img> container's background property (the <figure> in my example) to control the darkening. When the page is fully loaded, we add a .loaded class to the body. This does 2 things simultaneously:
Transition the opacity from 0 to 1 on the <figure>
Transition the semi-opaque background from (0, 0, 0, 0.5) to transparent
window.onload = init;
function init() {
document.body.classList.add("loaded");
}
body,
figure{
margin: 0;
}
figure {
position: fixed;
width: 100vw;
height: 100vh;
opacity: 0;
transition: 2s opacity;
}
img {
width: 100vw;
}
figure:after {
transition: 2s background;
background: transparent;
content: '';
display: block;
height: 100%;
width: 100%;
top: 0;
left: 0;
position: absolute;
}
.loaded figure:after {
background: rgba(0, 0, 0, 0.5);
}
.loaded figure {
opacity: 1;
}
<figure>
<img src="https://images.unsplash.com/photo-1432637194732-34cedd856522?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=a135be75b0fa480c18b22b5e557f56b3" alt="">
</figure>
http://codepen.io/antibland/pen/EKrVKr
Well, you can wait until the browser is done loading all images and then slowly change the opacity, like a fade-in effect. Here's a preview:
var imageElement = document.getElementById('image');
var overlayElement = document.getElementById('overlay');
window.addEventListener("load", function() {
imageElement.style.opacity = "1";
overlayElement.style.opacity = "1";
}, false);
body {
position: relative;
}
#image,
#overlay {
width: 1000px;
height: 800px;
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: all 2s ease-in-out;
-webkit-transition: all 2s ease-in-out;
}
#overlay {
background: rgba(0, 0, 0, 0.5);
}
<img id="image" src="https://upload.wikimedia.org/wikipedia/commons/3/3d/LARGE_elevation.jpg">
<div id="overlay"></div>
It's plain javascript. I know the tag only said css, but what you want is not possible with css only. I quickly created an overlay effect, don't mind the css except for: opacity: 0; and transition: all 2s ease-in-out; -webkit-transition: all 2s ease-in-out for the fade-in effect.
The javascript works like this: I create 2 variables which get the elements from the DOM. The image has an ID image and the overlay has an ID overlay. Next we set an eventlistener to our window. When the window is completely loaded, it should execute everything in the function. The opacities of both the image and overlay are set to 1 (visible). With our css property transition we manage the fade-in effect.

Flexboxes overlapping instead of pushing aside?

If you hover the green box at:
http://jsfiddle.net/frank_o/YS5QN/3/
It will expand and squeeze out the blue box. Is there a way to make it overlap the blue box instead, so the blue box remains in place?
HTML:
<div class="container">
<div class="column_1"></div>
<div class="column_2"></div>
</div>
CSS:
.container {
display: flex;
}
.column_1 {
flex: 1;
height: 60px;
background: blue;
}
.column_2 {
width: 120px;
height: 30px;
background: green;
}
jQuery:
$('.column_2').hoverIntent({
over: function () {
$(this).animate({
width: '100%'
}, 500);
},
out: function () {
$(this).animate({
width: '120px'
}, 500);
},
timeout: 300
});
I think you are mis-using display:flex.
Maybe try using width:calc() and position:absolute;
Try this out:
demo
Also, I wanted to show you how you can animate that box without using jQuery
.column_2 {
position: absolute;
right: 0;
width: 120px;
height: 30px;
background: green;
-webkit-transition: 500ms width;
-moz-transition: 500ms width;
-ms-transition: 500ms width;
-o-transition: 500ms width;
transition: 500ms width;
}
.column_2:hover {
width: 100%;
}
demo

Have two elements appear when their container is hovered, and then have one disappear when the other is hovered specifically?

I have two navigational elements that are set up as columns on either side of an image. You can see them in place at my website, here. Click on any image and after it loads, hover over it.
What I'm trying to accomplish is as follows:
When the cursor is outside of the image, both nav buttons are set at 0% opacity.
When the image is hovered in the center (not over either of the two nav buttons), both nav buttons are set at 50% opacity.
When either nav button is hovered directly, it is set at 100% opacity and the other nav button is set at 0% opacity.
This isn't working at the moment. HTML is as follows:
<div id="sb-body">
<a id="sb-nav-previous" class="sb-bignav" title="Previous" onclick="Shadowbox.previous()"></a>
<a id="sb-nav-next" class="sb-bignav" title="Next" onclick="Shadowbox.next()"></a>
<div id="sb-body-inner">
<img style="position: absolute;" src="Corrosion.jpg" id="sb-player" height="405" width="609">
</div>
</div>
And CSS is as follows:
#sb-nav-next {
right:0;
background:url('../images/nav-right.png') center center no-repeat;
}
#sb-nav-previous {
left:0;
background:url('../images/nav-left.png') center center no-repeat;
}
#sb-body:hover .sb-bignav {
opacity:0.5;
-webkit-opacity:0.5;
-moz-opacity:0.5;
}
#sb-nav-next:hover #sb-nav-previous,
#sb-nav-previous:hover #sb-nav-next {
opacity:0;
-webkit-opacity:0;
-moz-opacity:0;
}
.sb-bignav {
cursor:pointer;
position:absolute;
width:200px;
height:100%;
top:0;
z-index:400;
opacity:0;
-webkit-opacity:0;
-moz-opacity:0;
transition: opacity .125s ease-in;
-webkit-transition: opacity .125s ease-in;
-moz-transition: opacity .125s ease-in;
}
.sb-bignav:hover {
opacity:1.0;
-webkit-opacity:1.0;
-moz-opacity:1.0;
}​
Demo: http://jsfiddle.net/zNkcQ/
This can be done using pure CSS, but, you need to move the previous and next elements past the inner body element.
Demo: http://jsfiddle.net/SO_AMK/c5Xn3/
CSS:
#sb-body-inner {
height: 405px;
}
/* This is the height of the image inside the slider.
If you do not change this line than #sb-body-inner will be about 20px tall and
will not trigger the hover event */
#sb-body-inner:hover ~ #sb-nav-previous.sb-bignav,
#sb-body-inner:hover ~ #sb-nav-next.sb-bignav {
opacity: 0.5;
}
#sb-nav-previous.sb-bignav:hover,
#sb-nav-next.sb-bignav:hover {
opacity: 1.0;
-webkit-opacity: 1.0;
-moz-opacity: 1.0;
}
.sb-bignav {
cursor: pointer;
position: absolute;
width: 200px;
height: 100%;
top: 0;
z-index: 400;
opacity: 0;
-webkit-opacity: 0;
-moz-opacity: 0;
transition: opacity .125s ease-in;
-webkit-transition: opacity .125s ease-in;
-moz-transition: opacity .125s ease-in;
}
#sb-nav-next {
right: 0;
background: url('http://www.element17.com/images/nav-right.png') center center no-repeat;
}
#sb-nav-previous {
left: 0;
background: url('http://www.element17.com/images/nav-left.png') center center no-repeat;
}​
HTML:
<div id="sb-body">
<div id="sb-body-inner">
<img style="position: absolute;" src="http://www.element17.com/gallery/01_CONSTRUCTS/Shear.jpg" id="sb-player" height="405" width="609">
</div>
<a id="sb-nav-previous" class="sb-bignav" title="Previous" onclick="Shadowbox.previous()"></a>
<a id="sb-nav-next" class="sb-bignav" title="Next" onclick="Shadowbox.next()"></a>
</div>
​
The first problem is the specificity of each selector. The more specific (more points) overrides the less specific (fewer points).
ID: 100 points
Class: 10 points
Element: 1 point
Then, this rule has 110 points:
#sb-body:hover .sb-bignav {
opacity:0.5;
-webkit-opacity:0.5;
-moz-opacity:0.5;
}
Below, the rule has 10 points and is being overwritten by the previous rule with 110:
.sb-bignav:hover {
opacity:1.0;
-webkit-opacity:1.0;
-moz-opacity:1.0;
}​
Try this CSS:
#sb-nav-next {
right:0;
background:url('http://www.element17.com/images/nav-right.png') center center no-repeat;
}
#sb-nav-previous {
left:0;
background:url('http://www.element17.com/images/nav-left.png') center center no-repeat;
}
#sb-body:hover .sb-bignav {
opacity:0.5;
-webkit-opacity:0.5;
-moz-opacity:0.5;
}
#sb-body .sb-bignav:hover {
opacity:1.0;
-webkit-opacity:1.0;
-moz-opacity:1.0;
}
.sb-bignav {
cursor:pointer;
position:absolute;
width:200px;
height:100%;
top:0;
z-index:400;
opacity:0;
-webkit-opacity:0;
-moz-opacity:0;
transition: opacity .125s ease-in;
-webkit-transition: opacity .125s ease-in;
-moz-transition: opacity .125s ease-in;
}
Demo: http://jsfiddle.net/DmAVQ/
​
The second problem is that you can not do the third item only with CSS.
"When either nav button is hovered directly, it is set at 100% opacity and the other nav button is set at 0% opacity."
You need to use JavaScript to do this.
Well, I've exhausted all of my references for a css solution to this problem. The issue is that you'll never get the left nav overlay to become transparent because there is no way to select an element's preceding sibling. I used
#sb-body .sb-bignav:hover ~ .sb-bignav {
opacity: 0;
}
with success on getting the right nav overlay to become transparent, but that's it.
I suggest using jQuery to do this:
OLD
$('.sb-bignav:hover').siblings().css('opacity', 0);
NEW
$('.sb-bignav').hover( function(){
var self = $(this);
self.css('opacity', 1);
self.siblings('.sb-bignav').css('opacity', 0);
}, function(){
var self = $(this);
self.css('opacity', .5);
self.siblings('.sb-bignav').css('opacity', .5);
});
Just an idea...
Maybe you could do it by placing 2 clone navs in your anchor tags...
I made a fiddle:
http://jsfiddle.net/zNkcQ/5/
<div id="sb-body">
<a id="sb-nav-previous" class="sb-bignav" title="Previous" onclick="Shadowbox.previous()">
<span class="sb-img-next"></span>
<span class="sb-img-previous"></span>
</a>
<a id="sb-nav-next" class="sb-bignav" title="Next" onclick="Shadowbox.next()">
<span class="sb-img-previous"></span>
<span class="sb-img-next"></span>
</a>
<div id="sb-body-inner">
<img style="position: absolute;" src="Corrosion.jpg" id="sb-player" height="405" width="609">
</div>
</div>
.sb-img-previous{
left:0;
pointer-events: none;
background:url('http://www.element17.com/images/nav-left.png') center center no-repeat;
}
.sb-img-next{
right:0;
pointer-events: none;
background:url('http://www.element17.com/images/nav-right.png') center center no-repeat;
}
.sb-img-previous, .sb-img-next{
position: fixed;
width: 200px;
height: 100%;
etc...
}
#sb-nav-previous .sb-img-next,
#sb-nav-next .sb-img-previous,
#sb-nav-previous:hover .sb-img-previous,
#sb-nav-next:hover .sb-img-next{
opacity: 0.5;
pointer-events: none; //So each button will not be burdened by its duplicate...
}
#sb-nav-previous .sb-img-previous,
#sb-nav-next .sb-img-next,
#sb-nav-previous:hover .sb-img-next,
#sb-nav-next:hover .sb-img-previous{
opacity: 0;
}

Resources