Result looked for:
MODE 1: when the window is large (say >465px) the TOC items is displayed to the left of the content page
MODE 2: when the window's width gets smaller than 465px, reduce the width of the TOC item using transition
MODE 3: when the window's width gets greater than 465px, increase the width of the TOC item using a transition
finally, when the window's width < 465px and that the TOC is therefore hidden as a result of the mechanism described above, show some text on top that users can click on. When they click on this text, display the TOC item as an overlay. When you click on this text again, hide the TOC item as an overlay.
How to see the problem I try to get rid of:
increase the window to a large width and then back to small width. See the transitions when you go from one to the other. This is good.
make the window small so that the "Show Table of Content" text shows up. Click on the text. The TOC is displayed as an overlay. This is good. Then click again, to HIDE the TOC as an overlay. The cyan TOC disappears, but a transition is played right after. That's the problem. I want to get rid of this transition.
This behavior doesn't make sense to me, because the media query specifies that when the window < 465px the width of the TOC is 0. So why it is reset to 150px is a mystery to me. But the most important for me is, how do I get rid of this unwanted transition when the TOC as an overlay is removed (when the the 'overlay' class is toggled (off)?
function showMenuAsOverlay(caller) {
var node = document.getElementById("toc");
node.classList.toggle('overlay');
if (node.classList.contains('overlay'))
caller.innerHTML = "Hide Table of Content";
else
caller.innerHTML = "Show Table of Content";
}
.wrapper {
display: flex;
flex-direction: row;
border: 3px solid black;
z-index: -1;
position: relative;
}
.container-left {}
#toc {
border: 1px solid green;
flex: 0 0 auto;
white-space: pre;
z-index: -1;
width: 150px;
background-color: red;
transition: width 1s ease-out;
box-sizing: border-box;
}
.container-right {
display: flex;
border: 1px solid red;
flex 1 1 auto;
max-width: 400px;
background-color: white;
z-index:-1;
box-sizing: border-box;
}
.myicon {
cursor: pointer;
visibility: hidden;
}
#media
screen and (max-width: 465px) {
#toc {
width: 0;
background-color: purple;
transition: width 1s ease-out;
}
#toc.overlay {
z-index: 999;
position: absolute;
left: 0px;
background-color: cyan;
bottom: 0;
top: 0;
width: 150px;
transition: left 1s ease-out;
}
.myicon {
visibility: visible;
}
}
<body>
<div onclick="showMenuAsOverlay(this)" class="myicon" id="myicon">Show Table of Content</div>
<div class="wrapper">
<div class="container-left" id="toc" data-state="0">This is some text in the TOC</div>
<div class="container-right">
This is some content this is some content this is some more content, and this is content again and again.
</div>
</div>
</body>
The transition is happening when <div id="toc"> loses the class overlay.
That means you go from applying this rule:
#toc.overlay {
z-index: 999;
position: absolute;
left: 0px;
background-color: cyan;
bottom: 0;
top: 0;
width: 150px;
transition: left 1s ease-out;
}
to applying this rule:
#toc {
width: 0;
background-color: purple;
transition: width 1s ease-out;
}
This makes it clear why the transition is happening. You're going from width: 150px to width: 0 with this transition applied from #toc: width 1s ease-out;
Also, you've got this applied without a media query:
#toc {
border: 1px solid green;
flex: 0 0 auto;
white-space: pre;
z-index: -1;
width: 150px;
background-color: red;
transition: width 1s ease-out;
box-sizing: border-box;
}
This means the transition applies whatever the screen size. I don't think that's what you want. Put a media query around that block to only apply when you really want it to.
Related
I have a hover effect where when the icon image is hovered over, an larger image appears (for clarity). I want this larger image effect to end after three seconds AND still have the hover ability. If the image is moved off of, then came back to; I want the larger image to load for another three seconds. Every time the image is hovered over, the effect would last three seconds.
I have tried CSS animations, transitions, setTimeout and none of them are working like I need. Any help is appreciated. I have a LOT of code on this project, so I will try to only include the relevant parts. Thanks in advance.
I will have the code added to the question, once i figure out what I am doing wrong.
Code for building levels for hover image
#PlayerMarker1 {
position: absolute;
left:2%;
top: 2%;
z-index: 9;
}
#Player1Final{
position: absolute;
left:2%;
top: 2%;
z-index: 9;
}
/* Elements for Image load on hover*/
.playerMarker img{
margin: 0 5px 5px 0;
}
.playerMarker:hover{
background-color: transparent;
}
.playerMarker:hover img{
border: 1px;
}
.playerMarker span{ /*CSS for enlarged image*/
position: absolute;
padding: 0px;
left: -1000px;
/*background-color: black ;*/
visibility: hidden;
color: black;
text-decoration: none;
}
.playerMarker span img{ /*CSS for enlarged image*/
border-width: 0;
padding: 2px;
}
.playerMarker:hover span{ /*CSS for enlarged image*/
visibility: visible;
top: 0;
left: 100px; /*position where enlarged image should offset horizontally */
z-index: 50;
}
Code for defining the images.
<div id="Player1Test">
<a id="PlayerMarker1" href="#thumb1"><img src="Player Markers/Morty_Icon.png" width="auto" height="auto"/><span><img src="Player Images/Morty_Token.png" /><br /></span></a>
</div>
This script adds the playerMarker classes to the element I need.
/* Script to add class to player marker ID items */
function Player1Function() {
var Player1FinalTest = document.getElementById("PlayerMarker1");
Player1FinalTest.classList.add("playerMarker");
Player1FinalTest.id='Player1Final';
}
Seems like css animations to pulse the image would work fine. Run the code snippet to try.
img {
margin: 25px;
width: 100px;
height: auto;
}
img:hover {
animation: pulse 2s 1;
}
#keyframes pulse {
0% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.7);
}
50% {
transform: scale(1.4);
box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);
}
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
}
<h4>Hover the mouse over image<h4>
<img src="https://stackoverflow.design/assets/img/favicons/apple-touch-icon.png">
Yogi has a good answer using an animation that could be adapted to clearly move your element. I wanted to add an answer manipulating the left and top values using delay.
You are essentially moving a hidden image from off screen onto the screen. Though this feels a bit strange to do, as there may be more clear ways of accomplishing this task, you can immediately move the left into view, and delay moving the top out of view.
A different delay is needed for the hover and for the base element, so it returns to the original position immediately and is available for reuse, but delays moving away on hover.
This might keep in spirit of your current project.
If you have any questions, please ask 🚀
.playerMarker {
background-color: lightblue;
--size: 4rem;
height: var(--size);
width: var(--size);
}
.playerMarker span {
position: absolute;
padding: 0px;
top: 0;
left: -1000px;
visibility: hidden;
color: black;
text-decoration: none;
transition: top 0s;
}
.playerMarker span img {
border-width: 0;
padding: 2px;
}
.playerMarker:hover span {
transition: top 0s 2s;
visibility: visible;
top: -1000px;
left: 100px;
z-index: 50;
}
<div class="playerMarker">
<span>
<img src="https://stackoverflow.design/assets/img/favicons/apple-touch-icon.png" />
</span>
</div>
In mobile, I'm trying to create a toggle that appears on top of an image, that when tapped on, makes text appear on top of the image too.
I basically want to recreate how The Guardian newspaper handles the little (i) icon in the bottom right corner on mobile.
And on desktop, the the text is there by default under the image and the (i) icon is gone.
So far I've managed to find a similar solution elsewhere online but it's not quite working right as I need it to.
function toggleText() {
var text = document.getElementById("demo");
if (text.style.display === "none") {
text.style.display = "block";
} else {
text.style.display = "none";
}
}
#blog {
width: 100%;
}
#blog figure {
position: relative;
}
#blog figure figcaption {
display: none;
position: absolute;
bottom: 0;
left: 0;
box-sizing: border-box;
width: 100%;
color: black;
text-align: left;
background: rgba(0, 0, 0, 0.5);
}
#blog figure button {
position: absolute;
bottom: 0;
right: 0;
color: black;
border: 5px solid black;
}
<div id="blog">
<figure>
<img src="https://cdn2.hubspot.net/hubfs/4635813/marble-around-the-world.jpg" alt="A photo of a slab of marble for example">
<figcaption id="demo" style='display: none'>A photo of a slab of marble for example</figcaption>
<button type='button' onclick="toggleText()">(i)</button>
</figure>
</div>
Don't use IDs. Your code should be reusable!
Don't use inline JS on* handlers, use Element.addEventListener() instead
Don't use inline style attributes.
Don't use el.style.display === "something" to check for display styles. Use Element.classList.toggle() instead
This straightforward example uses JavaScript to simply toggle a className "is-active" on the button's parent, the figure Element.
Everything else (icon symbol change, caption animation etc...) is handled purely by CSS:
document.querySelectorAll("figure button").forEach(EL_btn => {
EL_btn.addEventListener("click", () => {
EL_btn.closest("figure").classList.toggle("is-active");
});
});
/* QuickReset */ * {margin: 0; box-sizing: border-box;}
img {
max-width: 100%; /* Never extend images more than available */
}
figure {
position: relative;
overflow: hidden; /* overflow hidden to allow figcaption hide bottom */
}
figure img {
display: block; /* prevent "bottom space" caused by inline elements */
}
figure figcaption {
position: absolute;
width: 100%;
bottom: 0;
padding: 1rem;
padding-right: 4rem; /* Prevent text going under the button icon */
color: #fff;
background: rgba(0, 0, 0, 0.5);
transform: translateY(100%); /* Move down, out of view */
transition: transform 0.3s; /* Add some transition animation */
}
figure.is-active figcaption {
transform: translateY(0%); /* Move into view */
}
figure button {
position: absolute;
width: 2rem;
height: 2rem;
bottom: 0.5rem;
right: 0.5rem;
border-radius: 50%;
color: #fff;
background: rgba(0, 0, 0, 0.5);
border: 0;
cursor: pointer;
}
figure button::before {
content: "\2139"; /* i icon */
}
figure.is-active button::before {
content: "\2A09"; /* x icon */
}
<figure>
<img src="https://cdn2.hubspot.net/hubfs/4635813/marble-around-the-world.jpg" alt="A photo of a slab of marble for example">
<figcaption>A photo of a slab of marble for example</figcaption>
<button type="button"></button>
</figure>
The above will work for any number of such elements on your website without the need to add any more CSS or JS.
I see a couple things that could mess this up, one is the fact that there is nothing to make your image adjust to your mobile screen, more-over there is also margin that is there by default, so I suggest these changes to the CSS:
First I'd set box-sizing to border-box and margin to 0, this should be a regular practice by the way.
*{
box-sizing: border-box;
margin: 0;
}
Then select the image and make it adjust to your page as such
#blog figure img{
height: auto;
width:100%;
}
Finally, for some styling you can add some padding to your blog div to make the image slightly smaller on your screen
#blog {
width: 100%;
padding: 35px;
}
This is the Fiddle for it.
I'm new in coding, so please be nice with me :)
I'm trying to show the hidden text on mouseover.
I would like a transion from right to left, but only where there is actually some hidden/ellipsised text ( I cannot know how long is it)
I'have something like this:
<div class="card">
<div class="text-box">
<h1> /*injected text*/ </h1>
</div>
</div>
css :
.text-box {
background-color: blue;
color:white;
}
h1 {
text-overflow: ellipsis;
overflow: hidden;
#include transition(left 4s linear);
overflow-x: hidden;
position: relative;
right: 0px;
}
.card:hover h1, .card:active h1 {
right:100px;
overflow: visible;
}
I need something similiar to the third, but only for ellipsised text
https://codepen.io/yurigor/pen/mAPkWP
thanks
Here's the code you only need from that codepen snippet
html
<div class="marquee bluebox">
<span><span>Hover over or touch me to see animated scrolling of this string. Fancy but buggy. May be still can be improved.</span></span>
</div>
css
.bluebox, .stuff {
box-sizing: border-box;
padding: 5px;
width: 300px;
border: 1px blue solid;
background-color: rgba(0, 0, 255, 0.4);
margin-bottom: 5px;
float: left;
}
.marquee {
white-space: nowrap;
overflow: hidden;
}
.marquee span {
display: inline-block;
width: 100%;
}
.marquee span span {
transition: left 4s linear;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span, .marquee:hover span {
width: auto;
}
.marquee:active span span, .marquee:hover span span {
left: calc(300px - 15px - 100%);
}
here's a demo
https://jsbin.com/dukukid/edit?html,css,output
the css code with a minor modification to avoid transition when the text going back to initial position. although i highly recommend you learn SASS because it makes the code snippet shorter as you can see in your link.
/*this function take a DOM element as an input, test if this element have an overflow
and then apply ellipsis and transition to it if its the case*/
function transitionEllipsised(element, textToAdd){
/*get the jQuery collection of this element to use jQuery innerHeight and innerWidth
methods on it and add the text to it*/
var $element = $(element).text(textToAdd);
//if the text did overflow in the width or the height of the container apply ellipsis transition
if (element.scrollHeight > $element.innerHeight()
|| element.scrollWidth > $element.innerWidth()) {
var innerHtml = $element.html();
//add marquee class to the element it will hide the overflow
$element.addClass("marquee")
//wrap the element in the two spans that will create the transition effect
.html(`<span><span>${innerHtml}</span></span>`);
}
}
//this is an example to use the function transitionEllipsised
/*when user click on the button the text on the input will be added to the h1 element
and apply transition only if text overflow*/
$("button.add-text").click(function(){
var headerExample = document.querySelector("h1.header-example");
//get the text of the user input
var textToAdd = $("input.text-to-add").val();
transitionEllipsised(headerExample, textToAdd);
});
/*hide overflow*/
.marquee{
white-space:nowrap;
overflow: hidden;
}
/*the css that you need to do the transition effect*/
.marquee span{
display: inline-block;
width: 100%;
}
.marquee span span{
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span,
.marquee:hover span{
width: auto;
}
.marquee:active span span,
.marquee:hover span span{
transition: left 4s linear;
left: calc(300px - 15px - 100%);
}
/*header of the example*/
h1.header-example{
/*important to fix the width and height of the container. if the text is longer the 300px there will be an overflow*/
width: 300px;
height: 40px;
border: red solid 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<!-- this is an example to use the function transitionEllipsised -->
<p>add some text using the input. if the text is longer then the container there will be transition effect to show the overflow</p>
<input type="text" class="text-to-add"><button class="add-text">add text</button>
<h1 class="header-example"></h1>
I have div called box with a header div as a child. when the div scrolls I want that header div to be sticked(fixed) to the top so the users can always see the header. when the user scrolls down,the header's height should decrease to take up less space but to still allow users to see the header content. When the user scrolls back up the header should be unstuck and the height should be like the way it was before any scrolling took place when it was at the top.
I don't like my attempt I'm about to show you because I get the offset of the box relative to the document. I feel like that might not be necessary because there might be a css solution. this one is for the scroll of the whole document. That demo shows using position fixed and it fixes to the top of the page. I cant use position fixed because I believe that is meant for the window and not for divs so what the next best thing?
I dont like how the header's width is over the scrollbars. and the animation is jumpy and it doesn't work.
$(function(){
var btop = $(".box").offset().top;
bwidth = $(".box").innerWidth();
$(".box").on("scroll", function(e){
if($(this).scrollTop() > 50){
$(this).find(".header").css({
"position" : "absolute",
"top" : btop,
"max-width" : bwidth,
}).animate({
"height" :"2em"
})
}else{
$(this).find(".header").css({
"position" : "static",
"top" : btop,
"max-width" : bwidth
}).animate({
"height" :"3em"
})
}
})
})
.box{
margin: 4em auto;
height: 12em;
width: 20em;
background: blue;
overflow-y: scroll;
/*overflow-x: hidden;*/
/*position: relative;*/
}
.header{
background: orange;
width: 100%;
height: 3em;
font-size: 1.3em;
}
.content{
width: 90%;
margin: 0 auto;
background: powderblue;
height: 12em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="box">
<div class="header">This will stick</div>
<div class="content">Other content</div>
<div class="content">Somemore content</div>
</div>
It's just an idea, but in your situation, you can fake a sticky header with a simple trick.
Remove the overflow-y: scroll property of your .box div.
Set a position: absolute property to your .header.
Add a div .content-container who contains your .content div and
set it a position: absolute property too and an overflow-y: scroll.
This way your header is always on top of your .box div and you can scroll your content. Then with your JS code you can change the height of your header on scroll event.
$(document).ready(function(){
$('.content').scroll(function(){
if ($('.content').scrollTop() >= 60){
$('.header').addClass('sticky');
} else {
$('.header').removeClass('sticky');
}
});
});
.box{
margin: 4em auto;
height: 360px;
width: 20em;
background: blue;
position: relative;
}
.header{
position: absolute;
top: 0;
background: orange;
width: 100%;
height: 60px;
font-size: 1.3em;
z-index: 9999;
transition: height 0.3s ease 0s;
-webkit-transition: height 0.3s ease 0s;
-moz-transition: height 0.3s ease 0s;
}
.header.sticky{
height: 30px;
}
.content{
position: absolute;
top: 0;
width: 100%;
height: 300px;
padding-top: 60px;
background: powderblue;
overflow-y: scroll;
}
.content > div{
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box">
<div class="header">This will stick</div>
<div class="content">
<div>Content</div>
<div>Somemore content</div>
</div>
</div>
If you see the code sample I have shared, you can see the overlay going outside the box. I traced the issue down to the transition attribute.
I want to remove the content outside of the div. Overflow isn't working as it is supposed to. (removing transition works, but I would like to keep it if possible)
Any help is appreciated
Codepen Link
CODE
var timer = setInterval(function() {
document.querySelector(".qs-timer-overlay").style.opacity = (document.querySelector(".qs-timer-overlay").style.opacity * 1) + 0.1;
if (document.querySelector(".qs-timer-overlay").style.opacity * 1 == 1) {
clearInterval(timer);
}
}, 1000);
.qs-main-header .qs-timer {
padding: 13px 10px;
min-width: 130px;
text-align: center;
display: inline-block;
background-color: #dd8b3a;
color: #FFF;
font-size: 20px;
border-radius: 50px;
text-transform: uppercase;
float: right;
cursor: pointer;
position: relative;
overflow: hidden;
}
.qs-main-header .qs-timer-overlay {
z-index: 1;
width: 10%;
max-width: 100%;
position: absolute;
height: 100%;
top: 0;
left: 0;
background-color: #c7543e;
opacity: 0.0;
/* border-radius: 50px 50px 0px 50px; */
}
.qs-main-header .qs-timer-content {
z-index: 2;
position: relative;
}
.scale-transition {
-webkit-transition: all 1s;
transition: all 1s;
}
<div class="qs-main-header">
<div class="qs-timer scale-transition ng-hide" ng-show="visibility.timer">
<div class="scale-transition qs-timer-overlay"></div>
<div class="qs-timer-content ng-binding">0 <span class="ng-binding">Sec(s)</span>
</div>
</div>
</div>
Actually it is the border-radius that is not getting respected when the transition is happening. This is because of creation of compositing layers for accelerated rendering and can be explained by having a look at the following articles:
HTML5 Rocks - Accelerated Rendering in Chrome
GPU Accelerated Compositing in Chrome.
Why does the issue not happen when transition is disabled?
When styles change but none of the criteria that necessitates the creation of a compositing layer is satisfied (that is, no animation or transition or 3D transform etc):
There is no compositing layer and so the whole area seems to get repainted at every change. Since a full repaint happens there is no issue.
View the below snippet (in full screen mode) after enabling "Show paint rects" and "Show composited layer borders" from Dev tools and observe the following:
No areas with an orange border (compositing layer) are created.
Every time the styles are modified by setting the focus on one of the a tags, the whole area gets repainted (a red or green blinking area).
.outer {
position: relative;
height: 100px;
width: 100px;
margin-top: 50px;
border: 1px solid red;
overflow: hidden;
}
.border-radius {
border-radius: 50px;
}
.inner {
width: 50px;
height: 50px;
background-color: gray;
opacity: 0.75;
}
a:focus + .outer.border-radius > .inner {
transform: translateX(50px);
height: 51px;
opacity: 0.5;
}
<a href='#'>Test</a>
<div class='outer border-radius'>
<div class='inner'>I am a strange root.
</div>
</div>
Why does adding a transition create a problem?
Initial rendering has no compositing layer because there is no transition yet on the element. View the below snippet and note how when the snippet is run a paint (red or green blinking area) happens but no compositing layer (area with orange border) is created.
When transition starts, Chrome splits them into different compositing layers when some properties like opacity, transform etc are being transitioned. Notice how two areas with orange borders are displayed as soon as the focus is set on one of the anchor tags. These are the compositing layers that got created.
The layer splitting is happening for accelerated rendering. As mentioned in the HTML5 Rocks article, the opacity and transform changes are applied by changing the attributes of the compositing layer and no repainting occurs.
At the end of the transition, a repaint happens to merge all the layers back into a single layer because compositing layers are no longer applicable (based on criteria for creation of layers).
.outer {
position: relative;
height: 100px;
width: 100px;
margin-top: 50px;
border: 1px solid red;
overflow: hidden;
}
.border-radius {
border-radius: 50px;
}
.inner {
width: 50px;
height: 50px;
background-color: gray;
transition: all 1s 5s;
/*transition: height 1s 5s; /* uncomment this to see how other properties don't create a compositing layer */
opacity: 0.75;
}
a:focus + .outer.border-radius > .inner {
transform: translateX(50px);
opacity: 0.5;
/*height: 60px; */
}
<a href='#'>Test</a>
<div class='outer border-radius'>
<div class='inner'>I am a strange root.
</div>
</div>
This illustrates that when the layers are merged back and full repaint happens, the border-radius on the parent also gets applied and respected. However, during transition only the compositing layer's properties are changed, so the layer seems to become unaware of the properties of other layers and thus doesn't respect the border-radius of the parent.
I would assume this to be because of the way rendering of layers work. Each layer is a software bitmap and so it kind of becomes equivalent to having a circular image and then placing a div on top of it. That would obviously not result in any clipping of content.
The comment in this bug thread also seems to confirm that a repaint happens when a separate layer is no longer required.
We want to repaint if "gets own layer" is going to change
Note: Though they are Chrome specific, I think the behavior should be similar in others also.
What is the solution?
The solution seems to be to create a separate stacking context for the parent (.qs-timer) element. Creating a separate stacking context seems to result in a separate compositing layer being created for the parent and this solves the issue.
As mentioned by BoltClock in this answer, any one of the following options would create a separate stacking context for the parent and doing one of them seems to resolve the issue.
Setting a z-index on the parent .qs-timer to anything other than auto.
var timer = setInterval(function() {
document.querySelector(".qs-timer-overlay").style.opacity = (document.querySelector(".qs-timer-overlay").style.opacity * 1) + 0.1;
if (document.querySelector(".qs-timer-overlay").style.opacity * 1 == 1) {
clearInterval(timer);
}
}, 1000);
.qs-main-header .qs-timer {
padding: 13px 10px;
min-width: 130px;
text-align: center;
display: inline-block;
background-color: #dd8b3a;
color: #FFF;
font-size: 20px;
border-radius: 50px;
text-transform: uppercase;
float: right;
cursor: pointer;
position: relative;
overflow: hidden;
z-index: 1; /* creates a separate stacking context */
}
.qs-main-header .qs-timer-overlay {
z-index: 1;
width: 10%;
max-width: 100%;
position: absolute;
height: 100%;
top: 0;
left: 0;
background-color: #c7543e;
opacity: 0.0;
/* border-radius: 50px 50px 0px 50px; */
}
.qs-main-header .qs-timer-content {
z-index: 2;
position: relative;
}
.scale-transition {
-webkit-transition: all 1s;
transition: all 1s;
}
<div class="qs-main-header">
<div class="qs-timer scale-transition ng-hide" ng-show="visibility.timer">
<div class="scale-transition qs-timer-overlay"></div>
<div class="qs-timer-content ng-binding">0 <span class="ng-binding">Sec(s)</span>
</div>
</div>
</div>
Setting opacity to anything less than 1. I have used 0.99 in the below snippet as it doesn't cause any visual difference.
var timer = setInterval(function() {
document.querySelector(".qs-timer-overlay").style.opacity = (document.querySelector(".qs-timer-overlay").style.opacity * 1) + 0.1;
if (document.querySelector(".qs-timer-overlay").style.opacity * 1 == 1) {
clearInterval(timer);
}
}, 1000);
.qs-main-header .qs-timer {
padding: 13px 10px;
min-width: 130px;
text-align: center;
display: inline-block;
background-color: #dd8b3a;
color: #FFF;
font-size: 20px;
border-radius: 50px;
text-transform: uppercase;
float: right;
cursor: pointer;
position: relative;
overflow: hidden;
opacity: 0.99; /* creates a separate stacking context */
}
.qs-main-header .qs-timer-overlay {
z-index: 1;
width: 10%;
max-width: 100%;
position: absolute;
height: 100%;
top: 0;
left: 0;
background-color: #c7543e;
opacity: 0.0;
/* border-radius: 50px 50px 0px 50px; */
}
.qs-main-header .qs-timer-content {
z-index: 2;
position: relative;
}
.scale-transition {
-webkit-transition: all 1s;
transition: all 1s;
}
<div class="qs-main-header">
<div class="qs-timer scale-transition ng-hide" ng-show="visibility.timer">
<div class="scale-transition qs-timer-overlay"></div>
<div class="qs-timer-content ng-binding">0 <span class="ng-binding">Sec(s)</span>
</div>
</div>
</div>
Adding a transform to the element. I have used translateZ(0px) in the below snippet as this also doesn't create any visual difference.
var timer = setInterval(function() {
document.querySelector(".qs-timer-overlay").style.opacity = (document.querySelector(".qs-timer-overlay").style.opacity * 1) + 0.1;
if (document.querySelector(".qs-timer-overlay").style.opacity * 1 == 1) {
clearInterval(timer);
}
}, 1000);
.qs-main-header .qs-timer {
padding: 13px 10px;
min-width: 130px;
text-align: center;
display: inline-block;
background-color: #dd8b3a;
color: #FFF;
font-size: 20px;
border-radius: 50px;
text-transform: uppercase;
float: right;
cursor: pointer;
position: relative;
overflow: hidden;
transform: translateZ(0px) /* creates a separate stacking context */
}
.qs-main-header .qs-timer-overlay {
z-index: 1;
width: 10%;
max-width: 100%;
position: absolute;
height: 100%;
top: 0;
left: 0;
background-color: #c7543e;
opacity: 0.0;
/* border-radius: 50px 50px 0px 50px; */
}
.qs-main-header .qs-timer-content {
z-index: 2;
position: relative;
}
.scale-transition {
-webkit-transition: all 1s;
transition: all 1s;
}
<div class="qs-main-header">
<div class="qs-timer scale-transition ng-hide" ng-show="visibility.timer">
<div class="scale-transition qs-timer-overlay"></div>
<div class="qs-timer-content ng-binding">0 <span class="ng-binding">Sec(s)</span>
</div>
</div>
</div>
The first two approaches are more preferable than the third because the third one works only on a browser that supports CSS transforms.
Yes, adding opacity: 0.99; to .qs-timer issue will fixed.
When opacity: 1 OR NOT define:
In this special case, there is no transparency involved so that gfx could avoid doing the expensive things.
In case Opacity: 0.99:
nsIFrame::HasOpacity() decides that there is an opacity, so gfx include valuable things. ( likes opacity with border-radius)
For more help Special case opacity:0.99 to treat it as opacity:1 for graphics , This ticket is not providing the opinion of our actual goal, but giving the idea about what is happening inside of CSS.