I have an inner and outer div. When the outer div changes from display: none to display: block, the inner div is supposed to transition from opacity 0 to opacity 1. This doesn't work however, the inner div just immediately goes to opacity 1. Any ideas why? Fiddle below -
http://jsfiddle.net/bradjohnwoods/umureqvq/
<div id="outer" class="hide">
<div id="inner" class="hide">
</div>
</div>
<button type="button">press</button>
div#outer{
height: 200px;
width: 200px;
background-color: tomato;
}
div#inner{
height: 100px;
width: 100px;
background-color: lightgrey;
opacity: 1;
transition: all 1000ms;
}
div#outer.hide{
display: none;
}
div#inner.hide{
opacity: 0;
}
var outer = $('#outer');
var inner = $('#inner');
var btn = $('button');
btn.click(function(event){
outer.removeClass('hide')
inner.removeClass('hide');
});
I think it's attempting the fade at the same time it's changing to be visible, so technically it's not visible yet. Therefore it's not doing the transition. Setting a timeout forces it to first be visible, then handle the opacity.
http://jsfiddle.net/umureqvq/6/
var outer = $('#outer');
var inner = $('#inner');
var btn = $('button');
btn.click(function (event) {
outer.removeClass('hide');
setTimeout(function () {
inner.removeClass('hide');
}, 0);
});
It has to do with the outer div's display property. You can set its width and height to 0 instead. It has the same effect but allows the inner div to transition.
Updated JSFiddle
CSS
div#outer{
height: 200px;
width: 200px;
background-color: tomato;
overflow: hidden;
}
div#inner{
height: 100px;
width: 100px;
background-color: lightgrey;
opacity: 1;
transition: all 1000ms;
}
div#outer.hide{
width: 0;
height: 0;
}
div#inner.hide{
opacity: 0;
}
display:none does not work well with transitions. I've used the following instead:
.hide {
display: block;
position: absolute;
top: -9999px;
left: -9999px;
}
In addition to addressing the transition issue, this also leads to a better user experience since the browser:
pre-fetches the resources of the element (eg. images), and
pre-renders the layout of the element
Another solution is to set a 1ms timeOut between the display and the opacity. I think that also is a bit tacky. I'm looking for a better solution, but I guess there is none.
Related
I have a stackblitz here
This should be the simplest thing but I can't see why its not working.
I have react app with Typescript and a styled components, I'm sure none of that is the problem this is just css.
I'm trying to position two divs on top of each other.
The container has position: relative;
And then the div are absolutely positioned.
.FlexContainerColOne,
.FlexContainerColTwo{
position: absolute;
top: 0;
left: 0;
}
But both div disappear, what am I missing
From what I am seeing here is that they are not disappearing, you just can't see them because they don't have a width assigned or content. See the following, I added width, and opacity to show the two divs merging over each other.
stackblitz snippet
Result:
flexcontainer {
position: relative;
}
.FlexContainerColOne,
.FlexContainerColTwo {
position: absolute;
top: 0;
left: 0;
}
.FlexContainerColOne {
background: red;
height: 500px;
width: 500px;
opacity: 0.5;
}
.FlexContainerColTwo {
background: green;
height: 500px;
width: 500px;
opacity: 0.3;
}
<flexcontainer>
<div class="FlexContainerColOne"></div>
<div class="FlexContainerColTwo"></div>
</flexcontainer>
I have a DIV with "width: 100%", and after some time it moves to a different width (for example "width: 50%") with a nice transition. I want that the part which is going to decrease to get a different color. How do I do it?
.container {
width: 80%;
height: 50px;
}
.bar {
background-color: red;
width: 100%;
height: 100%;
transition-duration: 1s;
}
<div class="container">
<div class="bar"></div>
</div>
You can simply put another bar exactly behind this bar. Set it's z-index to 1. And your current bar's z-index to a higher number.
The bar that is in the back, has a black color like you wanted.
Now when the red bar decrease it's width, the one in the back becomes visible.
Here you go, the most basic working example.
(Try hovering the bar and see it moving)
By simply overlaying a pseudo-element over the static .bar element, with position:absolute, it is places above the bar and has dynamic width which you should change.
.container {
width: 80%;
height: 50px;
}
/* static background bar */
.bar {
--progress: 80%; /* css variable */
position: relative;
background-color: salmon;
width: 100%;
height: 100%;
}
/* This is the part which moves: */
.bar::before{
content: '';
background-color: darkred;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: var(--progress);
transition: 1s;
}
.bar:hover {
--progress: 20%;
}
<div class="container">
<div class="bar"></div>
</div>
This solution uses a linear-gradient where I animate the background-size. I placed a fully black gradient on the .container, and a red one on the .bar, where I put a transition: background-size 1s on the black .container.
By using javascript to change a CSS variable, I can get the bar to animate.
Added a range to show-case the result.
Do note that it's always better to specify what attribute to animate with transiation, because otherwise the browser loops through all animatable properies, which can create janky animations.
let rangeInput = document.querySelector('input[type="range"');
let containerDiv = document.getElementById("container");
if (rangeInput) {
rangeInput.addEventListener('change', (event) => {
let newValue = event.target.value;
containerDiv.style.setProperty('--bar-width', `${newValue}%`);
});
}
input[type="range"] {
width: 80%;
margin-top: 1rem;
}
#container {
--bar-width: 100%;
width: 80%;
height: 50px;
background: linear-gradient(black, black);
transition: background-size 1s;
}
/* added "div" to obtain a higher specificity, to override the default background properties. */
div#container,
div.bar
{
background-repeat: no-repeat;
background-size: var(--bar-width);
}
.bar {
background: linear-gradient(red, red);
width: 100%;
height: 100%;
}
<div id="container">
<div class="bar"></div>
</div>
<input type="range" value="100" />
I'm trying to position a font-awesome button on top of a canvas. My current markup:
<li id="container">
<i class="fa fa-plus"></i>
<canvas></canvas>
</li>
The container and the canvas are visible by default. When the user mouse-overs the container, the button also appears. However, it pushes the canvas downward, causing it to spill out of the container:
The container has position: absolute and I don't have any control over that (it's part of a plugin I'm using). I do have full control over the styling of the canvas and the button.
What makes this tricky is that the user can resize the container, and the button has to remain on the top center of it at all times. Currently that works fine, but I can't get it to also appear on top of the canvas.
Hover to see i.
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
background-color: #F72F4E;
}
#container {
position: absolute;
width: 50vmin;
height: 50vmin;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,.2);
}
#container:hover i {
opacity: 1;
transition: opacity .2s ease-out;
}
#container i {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 3;
text-align: center;
opacity: 0;
transition: opacity .2s ease-in;
}
#container canvas {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border: 5px solid green;
}
<li id="container">
<i class="fa fa-plus">i</i>
<canvas></canvas>
</li>
Have you tried to utilize the z-index?
If you don't know what it is you can read up on it here: http://www.w3schools.com/cssref/pr_pos_z-index.asp
Essentially, you will have the button sit on top of all other elements.
Hope this gives some guidance.
Also! Just thought of this, try to mess around with the position property.
http://www.w3schools.com/cssref/pr_class_position.asp
The 'fixed' value will position your button relative to the DOM window, meaning other elements shouldn't have an effect on its position.
Resolved it by changing the font-awesome element to a div and setting its height to 0. It's z-index was already larger than that of the canvas.
I've noticed that transition is not working when the element is also changing from display none to block. Why is that? It works if I remove the display attribute.
CSS:
#box {
width: 150px;
height: 150px;
background: red;
transform: scale(0);
display: none;
transition: transform .5s;
}
#box.active {
transform: scale(1);
display: block;
}
http://jsfiddle.net/640kL55u/
Because it has display: none to begin with, the other styles are not being taken into the dom to be transitioned once display: block is added.
Instead, you can hide the div with height, so its still on the page but not showing. Then add the height on the show div.
JS Fiddle
Any change from or to display: none won't trigger transitions.
You can, however, change the display property and then add the class name at the end of the javascript stack. For instance:
function showElem(elem) {
elem.style.display = "block";
setTimeout(function() {
elem.classList.add("active");
}, 0);
}
And then pass element nodes to this function.
You can't transition with display: none; properties...
$("button").on("click", function() {
$("#box").addClass("active");
});
#box {
width: 0;
height: 0;
overflow: hidden;
background: red;
transform: scale(0);
transition: transform .5s;
}
#box.active {
width: 150px;
height: 150px;
transform: scale(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="box"></div>
<button>CLICK</button>
I am trying to position two DIVs over each other so that when the pointer hovers over the picture the top one fades to show the one underneath. I did this here: http://quaystreet.chrisloughnane.net/
I want make it responsive so the pictures would scale to the horizontal width of the mobile device. Which is no problem with one picture but as soon as I try to re-position the underneath DIV it breaks.
http://jsfiddle.net/chrisloughnane/f2NdQ/4/
Is it possible with just CSS to do what I want?
<div id='old'><img src="http://quaystreet.chrisloughnane.net/images/quay-street-old.jpg"/></div>
<div id='new'><img src="http://quaystreet.chrisloughnane.net/images/quay-street-new.jpg"/></div>
img {
max-width: 100%;
display: block;
margin: auto;
}
Here we go,
Live Example
CSS:
.images {
width: 100%;
position: relative;
max-width: 354px;
margin: 0 auto;
}
.images img {
position: absolute;
top: 0;
width: 100%;
max-width: 354px;
}
JavaScript:
$(document).ready(function() {
$('.images').on('mouseenter', function(){
$('.images .old').fadeOut(1000);
}).on('mouseleave', function(){
$('.images .old').fadeIn(1000);
});
});
HTML:
<div class="images">
<img class="new" src="http://quaystreet.chrisloughnane.net/images/quay-street-new.jpg">
<img class="old" src="http://quaystreet.chrisloughnane.net/images/quay-street-old.jpg">
</div>
Some things to you know:
To make each div in front of each other I am using position absolute.
I change the whole thing you did to make the div fadeOut, I think that way is more cleaner
I change your HTML to use the absolute position.
Your img will be width 100% and max-width 354px can be any value just need to be the maximum width your img will use. So when is less then 354px he will use the whole div with 100%.
Edit:
If you don't care about browser support you can use CSS3 transitions, beware no IE<10.
Here is the answer with transition
JavaScript it's not really necessary. You can achieve the same behaviour with a smooth CSS3 transition
.images {
position: relative;
margin: 0 auto;
}
.images img {
position: absolute;
top: 0;
left: 0;
width: 100%;
max-width: 354px;
-webkit-transition: opacity .8s linear 0s;
transition: opacity .8s linear 0s;
}
.images img:first-child {
z-index: 2;
}
.images img:first-child:hover {
opacity: 0;
}
example fiddle : http://jsfiddle.net/uNkY5/1/