Im new with HTML & CSS and this is my first question. I tried to make a box who scales from 1.0 to 0.8 when you hover it with your mouse.
It works fine when you're with the mouse in the middle (0.0 between 0.8) on the box.
But when you are between 0.8 and 1.0 area it goes crazy everytime I move my mouse.
I would like that the box scales to 0.8 when you hover the whole 1.0 area at any time. It should be scale back to 1.0 when I leave the fixed 1.0 area. Not any other area. I cant help myself.
Test it or see it: https://jsfiddle.net/cyLxLbya/
YouTube Video: https://youtu.be/4MT4hrK7DVE
(left is between 0-0.8, right goes crazy between 0.8-1)
The problem is your scroll event triggering and blurring while the element scales. You're detecting a :hover but when the element gets small enough it loses it's :hover state and tries to scale up again. And back again (as it goes into :hover again).
One of the ways to fix this would be to detect the hover on a parent element (that doesn't scale). For example: https://jsfiddle.net/cyLxLbya/1/
.box{
display: inline-block;
position: relative;
cursor: pointer;
box-shadow: inset 0px 0px 83px -8px rgba(0,0,0,0.75);
transition: all 200ms ease;
transition-duration: 0.2s;
}
.hover:hover .box{
transform: scale(0.8);
box-shadow: inset 0px 0px 24px 0px rgba(0,0,0,0.75);
}
It's also advisable to move the transition to the box itself (not the hover state of the box).
Related
my problem is I used some effect to make the card float using transform(translate) and some shadow and it works just fine, but whenever I come near the edges which is the end of the card width/height, it starts to glitch out with the animation, I believe I know why this is happening but I'm not quite sure how to fix it.. thanks!
just wanted to mentioned that the solution to that kind problems is wrapping the floating item with a wrapper and put the hover action on that wrapper not on the component itself.
so for example:
.card:hover{
box-shadow: -10px 0 10px 0;
transform: translate(10px, 10px);
}
Should turn into this:
.card-wrapper:hover .card{
box-shadow: -10px 0 10px 0;
transform: translate(10px, 10px);
}
So I've been trying this form challenge involving using no JS for interactive elements and I decided to make it 'fancy'. On click, the form drops and the arrow rotates; however, you can notice a jump in the pixels. I've viewed the box model several times and all of the pixels add up - I have no idea where this jump comes from. The only way to stop it is to make the arrow absolute, but it still isn't making sense why exactly that's happening if there's no shift in the layout. Any ideas?
https://codepen.io/mtbroomell/pen/zeMYdb
.ins {
display: block;
text-shadow:
20px 0 0 rgba(255,0,0,.6),
-20px 0 0 rgba(0,255,0,.6),
0 20px 0 rgba(0,0,255,.6);
font-size: 200px;
line-height:1;
color: transparent;
transform: rotate(0deg);
transition: .5s;
}
.form-toggle:checked ~ .ins-wrap .ins {
text-shadow:
0 0 0 rgba(0,0,0,.5),
0 0 0 rgba(0,0,0,.5),
0 0 0 rgba(0,0,0,.5);
transition: .5s;
transform: rotate(90deg);
}
^^^ The above is some of the sample styling as I'm not allowed to post CodePen without code.
I'm going to preface this by saying it seems quite smooth to me on a 2017 Macbook Pro using Chrome 72.
That said, almost all CSS animation jankiness on basic transforms can be improved by tricking the browser into using the GPU thread to render the element instead of the CPU. You can do that by forcing a 3d transform.
.animatedElement {
transform: translateZ(0);
}
Flickers and jumps in Chrome and FF can often be fixed with backface-visibility and perspective. Remember to use browser prefixes or a build tool that adds them.
.animatedElement {
backface-visibility: hidden;
perspective: 1000;
}
On their own, these don't do anything visually but they trick the browser renderer into doing some additional calculations.
I'm not sure what the native frame rate for css animations is but it's not fast enough. In animation the minimum frame rate needed to create the illusion of seamless movement is 24 fps. Using a requestanimationframe() would bump it up to 60 but then you'd need JS. I found this article on medium about CSS smooth animations. Might help? https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108
I noticed that my page was lagging when I hovered over an element with an animated box-shadow. Using Chrome's Devtools, I noticed that the entire page was being repainted when I hovered over the element. The repaint was taking 40+ milliseconds, or about 3 frames. The transition lasts about half a second, so there's noticeable lag during the half second.
How do I limit the repaint to just the area with the box shadow?
Here's a demo: http://jsfiddle.net/8sa41xfL/
html,body{
height:100%;
}
#test{
background:red;
height:100px;
width:200px;
transition:box-shadow 0.5s;
}
#test:hover{
box-shadow:0 0 3px 3px rgba(0,0,0,0.3);
}
<div id=test></div>
transform:translateZ(0) doesn't work on my page, but it works in the fiddle. Is there another fix aside from transform:translateZ(0)?
As mentioned in the thread linked in Pierre's answer box-shadow are expensive to paint. Explaining why it is expensive would require in-depth understanding of the way rendering works and I don't have near enough knowledge to explain it completely. But this answer attempts to explain why the whole page gets repainted and the various possible methods to avoid it.
According to CSS Triggers website:
Changing box-shadow does not trigger any geometry changes, which is good. But since it is a visual property, it will cause painting to occur. Painting is typically a super expensive operation, so you should be cautious.
Once any pixels have been painted the page will be composited together.
Why does the whole page get repainted everytime?
The below articles explain the way that painting actually works at a high level:
HTML5 Rocks - How Browsers Work - Painting
The Chromium Project - GPU accelerated rendering in Chrome
Based on those articles, we can see that each node in the DOM tree that produces a visual output is considered as a RenderObject and that each RenderObject is part of a RenderLayer directly or indirectly. Whenever a change happens, the renderer (or the render object) invalidates its rectangle (or RenderLayer) on screen and triggers a repaint.
In this case it seems like the whole page is getting repainted because the #test element does not warrant the creation of a separate RenderLayer (based on the criteria mentioned in the Chromium Project article) and so becomes a part of the root render layer. Because it is a part of the root render layer the whole page is getting repainted everytime a repaint is required.
The following snippet proves that the above assertion is correct. Here, I have added a #cover element (with positioning) to enclose the #test element. Now since the #cover element has explicit positioning, it creates an extra layer above root layer and #test becomes a part of this intermediate layer. Now, we can see that the box-shadow transition repaints only this intermediate layer and not the whole page.
html,
body {
height: 100%;
}
#cover {
position: relative;
}
#test {
background: red;
height: 100px;
width: 200px;
transition: box-shadow 0.5s;
}
#test:hover {
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3);
}
<div id=cover>
<div id=test></div>
</div>
What is the solution?
There are various CSS properties that can be used to address this problem but they all seem to point to the same point at a high level - which is, to create a separate render layer for the #test element.
Below are a few possible options to create a separate render layer for the #test element:
By adding explicit position properties - This is the same option described in Pierre's answer but absolute positioning is not the only option. Even relative positioning would solve it.
html,
body {
height: 100%;
}
#test {
position: relative;
background: red;
height: 100px;
width: 200px;
transition: box-shadow 0.5s;
}
#test:hover {
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3);
}
<div id=test></div>
By adding transparency (opacity) - Browsers seem to treat even opacity: 0.99 as adding transparency and it is very useful because adding this doesn't cause any visual difference.
html,
body {
height: 100%;
}
#test {
background: red;
height: 100px;
width: 200px;
opacity: 0.99;
transition: box-shadow 0.5s;
}
#test:hover {
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3);
}
<div id=test></div>
By adding a dummy CSS filter - We could add a filter: blur(0px) as it would do nothing.
html,
body {
height: 100%;
}
#test {
background: red;
height: 100px;
width: 200px;
-webkit-filter: blur(0px);
filter: blur(0px);
transition: box-shadow 0.5s;
}
#test:hover {
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3);
}
<div id=test></div>
CSS box shadows are expensive to paint. Read more on SO here.
If you want to avoid a full page repaint, use a position:absolute on your element. This will repaint the area that surrounds your element without affecting the whole page. Fiddle.
Can't find right values for styling menu here: http://demo.imatte.us/fomru/landingpage.html
Screen: i.imgur.com/iCBbIpP.png
just in safari, mac os.
Also, have another problem. When I'm choosing some element in first dropdown menu, then all panel bouncing some time. Think that's because 1 element in this menu has one style, and all other elements has another styles.
Screen: i.imgur.com/Bk5mbpF.png
Please, somebody, help me to find right css styles.
For the issue with the first dropdown menu: it's bouncing because the height of .filter-elements .element-all is 2 px less than for the other images. I've just changed the height from 22px to 24px and it doesn't bounce anymore. Because the image would be scaled inapproriate then, I'd suggest just to increase the margin-bottom by 2px:
.filter-elements .element-all
{
background: none repeat scroll 0 0 #e41b47;
box-shadow: 7px 8px #9bb3c8, 16px 0 #0c66bb, 7px -8px #85b560;
height: 22px;
margin: 8px 18px 8px 5px;
transition: all 0.5s ease-out 0s;
width: 22px;
}
changed into
.filter-elements .element-all
{
background: none repeat scroll 0 0 #e41b47;
box-shadow: 7px 8px #9bb3c8, 16px 0 #0c66bb, 7px -8px #85b560;
height: 22px;
margin: 8px 18px 10px 5px; // <-- increased margin here
transition: all 0.5s ease-out 0s;
width: 22px;
}
For the issue with Mac Safari - as I don't have a Mac here I can't test properly, but I guess it's an issue with the negative margin that's been set. There have been some known problems with Safari (don't know if they're already fixed) for elements having position: relative and a negative margin - Stackoverflow: Negative margin has different results on Mac Safari. You could try if changing the position:absolute for .filters .filter-name:after into position:relative would solve the Safari problem with the vertical alignment, but then you would have to take care about some follow up css-adjustments as this will affect the horizontal positioning.
I'm thinking on relying on box-shadow but it renders differently even on Firefox and Chrome/Chromium. The difference is very subtle with low values, but very noticeable with bigger ones.
In this example, you can see the differences arise when using negative values to make the shadow smaller. Left render is Chromium 25, right is Firefox 21.
HTML:
<div>
Hello there!
</div>
CSS:
div{
margin:100px;
padding:100px;
border:1px solid red;
box-shadow:0 80px 15px -85px #000;
}
How can I workaround this problem? Or maybe I should drop box-shadow by now?
Browsers use different algorithms to generate the shadow blur, in Chrome the opacity of shadow pixels decreases more quickly from the inner edge of the shadow area to the outer, and since the inner 1/3 of the shadow is hidden under the box in this example, it appears to look as having different start color. If we make the blur entirely visible by reducing the blur radius and the negative spread distance by 5px, and replace the solid shadow color with semi-transparent rgba(), the difference in the rendering becomes much less significant (demo).
Try to use the -moz-box-shadow property for firefox, it will render better.
div{
margin:100px;
padding:100px;
border:1px solid red;
-moz-box-shadow: 0 80px 15px -85px #000;
box-shadow:0 80px 15px -85px #000;
}