Stacking Order Changes with CSS3 Animation - css

I was following a guide for making a ribbon with CSS. However, I attempted to modify this by adding a CSS3 Animation to the position, as seen in this JSFiddle.
As you can see, with the animation, the main ribbon element falls behind the :before & :after pseudo-elements, instead of above them as it should (and does without the animation). I've tried explicitly setting the z-index on all elements but it doesn't seem to affect this. Does anyone know why this would be happening, or what I can do to fix it? For the record, I'm viewing through the latest Google Chrome and am not worried about cross-browser compatibility for the moment. Thank you!
Here's the ribbon code:
.ribbon {
font-size: 16px !important;
/* This ribbon is based on a 16px font side and a 24px vertical rhythm. I've used em's to position each element for scalability. If you want to use a different font size you may have to play with the position of the ribbon elements */
width: 50%;
position: relative;
background: #ba89b6;
color: #fff;
text-align: center;
padding: 1em 2em;
/* Adjust to suit */
margin: 2em auto 3em;
/* Based on 24px vertical rhythm. 48px bottom margin - normally 24 but the ribbon 'graphics' take up 24px themselves so we double it. */
/*CODE I ADDED*/
animation: flyRibbon 30s linear infinite;
-webkit-animation: flyRibbon 30s linear infinite;
}
.ribbon:before, .ribbon:after {
content:"";
position: absolute;
display: block;
bottom: -1em;
border: 1.5em solid #986794;
z-index: -1;
}
.ribbon:before {
left: -2em;
border-right-width: 1.5em;
border-left-color: transparent;
}
.ribbon:after {
right: -2em;
border-left-width: 1.5em;
border-right-color: transparent;
}
.ribbon .ribbon-content:before, .ribbon .ribbon-content:after {
content:"";
position: absolute;
display: block;
border-style: solid;
border-color: #804f7c transparent transparent transparent;
bottom: -1em;
}
.ribbon .ribbon-content:before {
left: 0;
border-width: 1em 0 0 1em;
}
.ribbon .ribbon-content:after {
right: 0;
border-width: 1em 1em 0 0;
}
Here's the animation code:
#keyframes flyRibbon {
100% {
transform: translateX(200vw);
-webkit-transform: translateX(200vw);
}
}

Adding a div around the ribbon and applying the animation css to it instead of to the h1 element should fix this.
HTML:
<div class="container">
<h1 class="ribbon">
<strong class="ribbon-content">Everybody loves ribbons</strong>
</h1>
</div>
CSS:
.container {
animation: flyRibbon 30s linear infinite;
-webkit-animation: flyRibbon 30s linear infinite;
}
JSFiddle

This is not a bug. This is a specified behavior of z-index for elements that create stacking contexts, and .ribbon creates a stacking context because it has transform (in the animation). With transform, the element becomes the root of the stacking context and no child box can be placed below it.
As a workaround without extra markup, you can give the inner contatiner block display and position it above the ribbon ends, like in this example.

Related

Transition for moving objects with position: fixed?

This seems like it should be a simple problem, but I'm by no means a CSS expert, and I've been beating my head against the wall trying to figure it out. So I've got a ContentHeader element, and when the user scrolls down past a certain point, I want it to slide up to cover the NavigationHeader element. I'm changing the position of ContentHeader by changing the className property from "content-header" to "content-header top", which works, but ContentHeader just jumps into the new position instead of transitioning smoothly. This is the CSS I'm using currently:
.content-header {
position: fixed;
top: 50;
width: inherit;
z-index: 1030;
padding: 12px 15px 12px 15px;
transition: top 1s linear;
}
.content-header.top {
top: 0;
}
If you need to see the JavaScript, let me know and I can add that as well, but it's basically just doing ...
<section className={className} ...
... where the value of className would vary depending on where ContentHeader should be positioned. I thought maybe the problem was that this is happening inside a React render block and that was skipping the transition, but I tried changing the class with an onClick event that wouldn't force a re-render, and the results were the same. If anyone could help, I'd appreciate it!
You're missing px on your top value, which should read top: 50px;
$('button').on('click', function() {
$('h1').toggleClass('top');
})
.content-header {
position: fixed;
top: 50px;
width: inherit;
z-index: 1030;
padding: 12px 15px 12px 15px;
transition: top 1s linear;
}
.content-header.top {
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 class="content-header">header</h1>
<button>click</button>
That said, I would use transform: translateY(); instead of top because that's more performant. Using a transition or animation with transform get GPU acceleration, where transitioning top does not.
$('button').on('click', function() {
$('h1').toggleClass('top');
})
.content-header {
position: fixed;
transform: translateY(50px);
width: inherit;
z-index: 1030;
padding: 12px 15px 12px 15px;
transition: transform 1s linear;
}
.content-header.top {
transform: translateY(0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 class="content-header">header</h1>
<button>click</button>
Try giving the initial top value a unit, for example: top: 50px.
.content-header {
position: fixed;
top: 50px; // add `px` unit here
width: inherit;
z-index: 1030;
padding: 12px 15px 12px 15px;
transition: top 1s linear;
}

How can i fixed safari sub-pixel bug on elements with overflow: hidden?

I'm trying to create a box with label on left top angle. This label must slide on mouse over.
When I hover on this box In Safari Browser (Mac OS El Capitan) I watch the following bug: http://newsletters.loginov.biz/1.png
When the transition is complete yellow label becomes ok (clipping is well).
NB! I discovered that this happens when the viewport width is odd. (You can resize browser step by step to see this problem).
Any ideas?
.box {
position: relative;
overflow: hidden;
left: 50%;
margin-left: -100px;
width: 200px;
height: 200px;
background: #212121;
box-shadow: 0 0 8px rgba(0,0,0,.13);
-webkit-transition: box-shadow 250ms;
transition: box-shadow 250ms;
}
.box:after {
position: absolute;
z-index: 1;
top: 0;
right: 0;
border-left: 60px solid transparent;
border-top: 120px solid #ffcc32;
content: '';
-webkit-transform: translate(30px, -60px);
transform: translate(30px, -60px);
-webkit-transition: transform 250ms;
transition: transform 250ms;
}
.box:hover {
box-shadow: 0 0 45px rgba(0,0,0,.35);
}
.box:hover:after {
-webkit-transform: none;
transform: none;
}
<div class="box">
<img src="http://s.appleinsider.ru/2016/06/macOS-Sierra-Wallpaper-iPhone-Plus-Wallpaper.jpg" alt="test img" />
</div>
I know, this is not an elegant solution, but helped me with exactly the same problem.
In my case there were multiple elements in row and issue was reproduced when wrapper element was centered. So when wrapper has odd width while viewport has odd width too it can't be perfectly centrified in Safari (the same for even width). So your wrapper had to have an opposite fold.
JQuery in my solution is for fast add/remove class - you can use your own methods.
var $wrapper = $('.wrapper'), fixSafariSubpixelDelay;
function fixSafariSubpixel() {
clearTimeout(fixSafariSubpixelDelay);
fixSafariSubpixelDelay = setTimeout(function() {
if (window.innerWidth % 2 == 0)
$wrapper.removeClass('even').addClass('odd');
else
$wrapper.removeClass('odd').addClass('even');
}, 100);
};
window.addEventListener('resize', fixSafariSubpixelDelay);

Pseudo elements transition on IE 11 ignores padding

Trying to do a button hover effect I stumbled upon this weird bug on IE.
It's happening even on IE11.
When you hover over the button the pseudo elements 'jump' their transition.
If you remove the padding, it stops!
I've been trying to work around it the whole afternoon, but I can't seem to find the problem.
Here's the demo: http://codepen.io/anon/pen/rVwRKL
HTML
Live Button
CSS
body
{
padding: 5em;
margin: 0;
}
a{
padding: 1em 1em;
margin: 0;
box-shadow: inset 0px 0px 0px 3px blue;
position: relative;
box-sizing: border-box;
display: inline-block;
}
a::before,
a::after
{
transition: width 0.4s ease, height 0.4s ease 0.4s, opacity 0.4s ease;
content: " ";
box-sizing: border-box;
width: 100%;
height: 100%;
display: block;
position: absolute;
border: solid 3px green;
display: inline-block;
}
a::after
{
right: 0;
bottom: 0;
border-right-color: transparent;
border-top-color: transparent;
}
a::before
{
left: 0;
top: 0;
border-left-color: transparent;
border-bottom-color: transparent;
}
a:hover::before,
a:hover::after
{
transition-delay: 0.4s, 0s, 0.7s;
width: 0;
height: 0;
opacity: 0;
}
Thanks!
Not sure if you ever got an answer to this Marlon but I've just come across basically the same issue with IE. Thankful I've managed to figure out the oddity in IE that is causing the issue.
It appears to be when you are mixing your measurement prefixes i.e. px, %, em, vw, etc...
In my issue I was going from a vw to px - this worked fine everywhere except IE. As soon as I changed my vw to a px everything worked fine.
In your example above it was even less obvious to spot. You have the before/after set to a width of 100% - % being the measurement. Then, in the hover state, you had them both simply set to 0 (zero) with no measurement. This is where the problem is because no measurement isn't the same as % which IE appears to struggle to figure out (?!?!?!). As soon as you add the % to the width/height on the hover state it works fine.
See working example here with the adjusted width/height: http://codepen.io/anon/pen/YyNWzw
Previous CSS
a:hover::before,
a:hover::after
{
transition-delay: 0.4s, 0s, 0.7s;
width: 0;
height: 0;
opacity: 0;
}
Adjusted CSS
a:hover::before,
a:hover::after
{
transition-delay: 0.4s, 0s, 0.7s;
width: 0%;
height: 0%;
opacity: 0;
}
Typically I would also never bother adding a measurement when the value is 0 (zero) but I guess if you're using transitions then IE requires it to match.
Hope this helps.

Fill button with a different color on hover

Is there anyway to use CSS to achieve the above effect when mouse over on the button?
Thanks!
You can achieve what you are looking for by using a background gradient:
Create your gradient with two stops at 50%, your two colours on either side of the stops.
Make your background take up 200% the width of the element with background-size
Have your background position itself -100%
Move the background into position on :hover.
Note: Be sure to include browser prefixes where appropriate.
.menu{
padding: 20px 40px;
font-size: 32px;
font-family: Arial, sans-serif;
background: #F00;
display: inline-block;
background: linear-gradient(to right, #f8b3b5 0%, #f8b3b5 50%, #ffffff 50%, #ffffff 100%);
background-size: 200% 100%;
background-position: 100% 0;
transition: background-position 0.3s;
}
.menu:hover{
background-position:0 0;
}
<div class='menu'>Menu</div>
demo - http://jsfiddle.net/victor_007/1y2jw6wh/
added pseudo element :before and background-color
.menu {
padding: 20px 40px;
font-size: 32px;
font-family: Arial, sans-serif;
display: inline-block;
position: relative;
}
.menu:before {
content: '';
background: #FFADAD;
position: absolute;
width: 0%;
top: 0;
left: 0;
height: 100%;
transition: 0.3s linear;
z-index: -1;
}
.menu:hover:before {
width: 100%;
}
<div class='menu'>Menu</div>
There is, a working fiddle here: http://jsfiddle.net/84fpp167/
You basically make a wrapper div, position the div you want to slide absolute to it. Then you use the :hover on the wrapper div to transition the absolute position of the slide div untill the position is left:0 with a speed of 1 second.
.wrapper {
position: relative;
overflow: hidden;
width: 100px;
height: 100px;
border: 1px solid black;
}
#slide {
position: absolute;
left: -100px;
width: 100px;
height: 100px;
background: #FFADAD;
transition: 1s;
height:100%;
}
.wrapper:hover #slide {
transition: 1s;
left: 0;
}
At first search the stack
You must read about css transitions, you will be use ease-in and background-color properties.
http://www.w3schools.com/css/css3_transitions.asp
Nobody gone code it for you, make an effort and do somethibg with your own.
The transitions showroom - http://codepen.io/davekilljoy/pen/wHAvb, mess with the code to make desired effect. Njoy !
Post with the similar problem :
form stack search 1
form stack search 2

CSS combination of :after and :hover:after on multiple HTML tags not behaving correctly

I am currently running into a problem when trying to implement a simple rollover using CSS :after and :hover pseudo-elements.
Have a look at the clock and facebook icons to the right: http://clean.philippchristoph.de/
Here's the CSS code:
.icon {
background: url('../img/clock_icon.png') top left no-repeat;
width: 25px;
height: 25px;
}
.icon:after {
.transition(opacity, .2s, ease);
content: " ";
position: absolute;
top: 4px; left: 5px; bottom: 0; right: 0;
background: url('../img/clock_icon.png') no-repeat;
background-position: -25px 0;
opacity: 0;
}
.icon:hover:after, .clock:hover div {
opacity: 1;
}
As you can see, the image is faded using a sprite and opacity. However, now I can't seem to hover both elements anymore. As you will see on the example page, you can hover over the facebook icon, but not over the clock. If you remove the facebook icon, you can hover over the clock again. Note that the two icons are entirely seperate elements.
I've tested this behavior on both FF and Chrome on Windows.
It'd be awesome if someone could shed some light onto this issue.. :)
Replace your CSS with this one (I mean the mentioned classes only, not your entire CSS :) ):
.icon {
background: url("../img/clock_icon.png") no-repeat scroll left top transparent;
height: 25px;
width: 25px;
position: relative
}
.icon:after {
-moz-transition: opacity 0.2s ease 0s;
background: url("../img/clock_icon.png") no-repeat scroll -25px 0pt transparent;
bottom: 0pt;
content: " ";
left: 0;
opacity: 0;
position: absolute;
right: 0pt;
top: 0;
}
.icon:hover:after, .clock:hover div {
opacity: 1;
}
.facebook, .facebook:after {
background-image: url("../img/facebook_icon.png");
}
.clock {
position: relative
}
.clock div {
-moz-transition: opacity 0.2s ease 0s;
color: #A0A0A0;
font-size: 12px;
left: 40px;
line-height: 11px;
opacity: 0;
position: absolute;
top: 5px;
width: 160px
}
You need to add position: relative to your icon class, so that the generated content is positioned relative to that, rather than the parent. I've tried to simplify what you have in a fiddle, though I wasn't 100% sure what you are after. Is that close? I also amended the positioning of the generated content.
It's worth noting that - annoyingly - you can't apply a transition to generated content (which is why any attempt to have the opacity transition on these elements will fail in your case). Hopefully this will change soon.

Resources