Css scale text still blurry after searching on StackOverflow - css

URL: https://www.royalsmushicafe.dk/
I have issues with the left side menu text looking blurry on mouseover. It's as if it's blurry during the animation and turns crisp again only after the animation is over. In Safari it stays blurry.
I'm using Transform: scale(1.2) and -webkit-font-smoothing: subpixel-antialiased;, but have tried quite a lot of suggested solutions.
I've been browsing StackOverflow and Google without luck, with suggestions like using transform perspective(1px), scale3d, translate3d( 0, 0, 0), backface-visibility: hidden even filter: blur(0) and whatnot – nothing has resulted in the expected behaviour of a crisp text scaling on mouseover :(
Any help would be much appreciated

I've just had almost the exact same problem, and found all the same hack ideas for perspective(1px), backface-visibility: hidden, and so on, with no success. Chrome and Firefox are fine, but scaled-up text blurs horribly in Safari. For anyone else experiencing this, the band-aid solution is to scale down instead of up.
In my case, I have a label that moves and changes scale when the input has content:
label {
will-change: transform, color;
transform: translate3d(0,0,0);
transform-origin: top left;
height: 20px;
}
input:placeholder-shown:not(:focus) + label {
transform: translate3d(0,.6rem,0) scale3d(1.5,1.5,1);
}
Idea here is that the label has the same styles if the input is focused or has content, and is bigger if the input is empty and unfocused (hence the funky pseudoclass selector.)
The problem is that using transform like this triggers GPU compositing on the <label>. When this happens, the composited layer is rendered like a bitmap in the GPU, at the dimensions calculated during CSS layout (20px here). Then, the GPU layer is scaled up (in this case by 1.5x, so it's now 30px high, and blurry).
Chrome and Firefox seem to re-render the layer at final scale which un-blurs it. Safari does not, probably to save memory since the composited layer is dimensionally smaller (20px high instead of 30px).
To make it work better, I opted to scale down:
label {
will-change: transform, color;
/* reverse the scaling ratio */
transform: translate3d(0,0,0) scale3d(0.67, 0.67, 1);
transform-origin: top left;
height: 20px;
}
input:placeholder-shown:not(:focus) + label {
/* reset to scale of 1 */
transform: translate3d(0,.6rem,0) scale3d(1,1,1);
}
The scaled-down text is a tiny bit blurry, but much less noticeably. I might try different -webkit-font-smoothing values, although I don't hold out a lot of hope because of the way GPU rendering works. Scaling ratios that resolve to a clean, integer pixel font size will probably work better, too.

Would backface-visibility: hidden; help? I recall having similar problems and it did help.

Related

High render usage with animations on mouse move

I found some interesting behavior when testing the performance of some CSS animations. For example, I can animate these 1,000 elements and on my PC they are barely using any resources.
It's honestly impressive that it preforms that well, but if I'm moving the mouse, it's a completely different story.
The only difference is that I am constantly moving my mouse. I want to know why this happens, and if there is anything I can do to improve it. None of these elements have any mouse interaction, no JavaScript listeners, no CSS hover effects or anything like that. I am confused why moving the mouse would then have such a major effect. This high resource usage also happens even when the elements aren't visible and are scrolled past. The window is focused for all benchmarks.
The animation that I am talking about are using transforms and opacity. When using other properties like width, height, margin I get high resource usage no matter what.
Here are several things that I have tried to change this with no noticeable difference in performance.
pointer-events: none, unsurprisingly no effect. I didn't think it worked like that.
will-change
display: inline-block vs position: absolute layout
transform vs opacity animations
translate3d vs translate
Elements outside of the viewport (scrolled past)
I'm guessing this has to do with a GPU and as soon as the mouse moves, it requires the CPU to do something. This would explain the lack of difference on properties that require to CPU to calculate, and properties that can use the GPU are effected so dramatically.
I'm noticing this using Brave and Edge for sure. I don't under the Firefox tool enough to confidently say the same for them, although it appears to happen as well.
How can I make this always run as in the first case? I am never using any mouse interaction, so these elements could careless what it happening with the mouse from my perspective.
Here is a code snippet that should be able to produce the effect. I also have here on a GitHub pages site.
https://jack-stoller.github.io/so_demo.html
<style>
body {
padding-bottom: 150vw;
}
div {
position: absolute;
height: 50px;
width: 50px;
pointer-events: none;
will-change: transform;
background-color: red;
animation: Animation 2s ease infinite;
}
#keyframes Animation {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
</style>
<body></body>
<script>
const size = 50 + 8 + 8;
const count = Math.floor(window.innerWidth / size);
[...Array(1000)].forEach((_, i) => {
let div = document.createElement('div');
div.style.top = Math.floor(i / count) * size + 'px';
div.style.left = Math.floor(i % count) * size + 'px';
document.body.appendChild(div);
});
</script>

How can you reliably use relative units for background-position when using a background-image with background-size=cover?

I've run into an issue when using background-position in a div along with background-size: cover. There seem to be some quirks in the browsers calculations, so I'm looking for a reliable way of doing this.
More detail...
The use case is mostly visual and everything in the interface should scale nicely. In the past I've has good results by either using rem or em units for everything.
At the start or when the screen size changes I'm measuring the available screen space and then set an appropriate font-size on the container. Something like this...
const size = calculateSize();
$("#container").css({fontSize: size + 'px'});
Generally, it works very nicely. Everything scales and positions itself properly - or does it?
I recently added a graphic button - a with a background image.
.button {
background-image: url("img/button.png");
background-size: cover;
width: 10em;
height: 4.5em;
cursor: pointer;
}
.button:hover {
background-position-x: -100%;
}
I did also try background-position-x: -10em, but I prefer the percentage notation as it takes care of itself if I resize the button image.
That's when I started noticing a small, but annoying problem. When I hover over the button, it moves just a little bit. The amount varies depending on how large the available space is. It's usually only a pixel or 2 at the most. It seems equally affected by Chrome, Firefox, and Edge.
It might not seem like much, and maybe I can just accept it as a feature, but I'm wondering if anyone else has experienced this and found a way around it.
One likely solution would be to just use separate images for the different button states, but I prefer keeping the number of images to a minimum.
UPDATE: So, I just tried creating 2 separate images, and then changed the CSS accordingly...
.button {
background-image: url("img/button0.png");
background-size: cover;
width: 10em;
height: 4.5em;
cursor: pointer;
}
.button:hover {
background-image: url("img/button1.png");
/* background-position-x: -100%; */
}
This does make the wobble movement go away, so I'm pretty confident it's some specific issue with how the browser is interpreting background-position-x. Being such a small movement, I suspect it's some sort of rounding error.
Minimal, Reproducible Example:
In an attempt to ensure I wasn't just seeing things, I put together a jsFiddle that illustrates the problem...
https://jsfiddle.net/xtempore/nfLh86sm/8/
I made a simplified version of the button image. It's just black on the left half and very pale grey on the right. Then I put it into 4 different divs each with a different font-size.
When you hover, you should just see the rectangle change from black to grey. And on the 1st and 3rd ones it does. But check out the 2nd and 4th ones! When you hover, there's a sneaky little bit of black appears on the left-hand edge.
The units used are pretty straightforward in this case. The problem seems to appear with odd-numbered pixels. In my case sometimes these font-sizes will also include decimals (e.g. 15.45px).
This problem demonstrates an issue with rendering in the common browsers (Chrome, Firefox, Edge), but I managed to find an alternate method that gives the desired result.
Instead of using...
background-size: cover;
... you can use a percentage, for example ...
background-size: 200%;
If your base image is 2 sprites wide, i.e. contains two images for different states side-by-side, then the specified background-size should be 200%. Similarly, if you have 3 times the size, 300%, and so on.
This gives the desired scaling, even as the div changes size.
You can see that the problem is resolved in the example fiddle by just changing that value from cover to 200%.
With problem: https://jsfiddle.net/xtempore/nfLh86sm/8/
No problem: https://jsfiddle.net/xtempore/2vcg4h1L/
I hope this helps someone else who is getting these weird side-effects.

css animation: transform origin not appearing to work correctly

I am working on this 3 panel card opening animation.. Here is an example of what I have so far.. example. This is the class that I'm applying for the second animation and transform-origin just doesn't seem to do what I think it should.. But I'm pretty new at this animation stuff.
.two-right {
transform: rotateY(170deg);
transform-origin: 100% 0;
}
As you can see the problem is that I cant get the second animation to open correctly.. On the left side it works just fine but on the right the card isn't opening correctly on the right side of the card.. Right now I'm just poking around and haven't been able to find anything. Any help would be appreciated.
Okay I found the answer to my own question.. The reason is that the flip is based on it's parent.. That's why it is rotating on the wrong axis but after it's scaled and the animation is complete it ends up being positions in the correct location.
Instead of trying to do the animations I put a timeout in the javascript to let it scale and then add the flip animation later. Here is the completed code.
Complete example
.two-right {
/* transform: rotateY(170deg); */
transform-origin: 100% 0;
}
.two-flip {
transform: rotateY(160deg);
}
I first add the .two-right class and then the .two-flip half a second later.

flot.js - position ticks vertically, but being cut off and centered

I am using flot.js for charts with timestamp on the x-axis. As I will have quite a lot of ticks on these charts I am rotating them vertically so they do not overlap. This works fine, but the labels are centered on the tick and there is not enough room provided so they are cutoff.
I am NOT using the tickrotor plugin at tickrotor. I tried it and there were more problems than benefits. Instead I am using plain css which I found here on SO via rotate tick labels, however, in the post it appears they are not having the problem I am (perhaps there was some missing information there?).
Furthermore, I need to support IE8. The post mentioned above talks about using filter or -ms-filter, but fails to mention the css to accomplish that.
I was under the impression that even with the tick rotation it would correct the height accordingly, but that doesn't seem to the case. I also checked out flot's github and while they mention working on this feature it has still not been implemented.
I know a lot of people have the need to rotate the ticks, but I have not found anything which resembles my issue (centered and cutoff).
Any help or ideas would be appreciated.
#flot_chart div.xAxis div.tickLabel
{
transform: rotate(-90deg);
-ms-transform:rotate(-90deg); /* IE 9 */
-moz-transform:rotate(-90deg); /* Firefox */
-webkit-transform:rotate(-90deg); /* Safari and Chrome */
-o-transform:rotate(-90deg); /* Opera */
/*rotation-point:50% 50%;*/ /* CSS3 */
/*rotation:270deg;*/ /* CSS3 */
}
You are going to have lots of problems rotating the labels yourself. This is why the flot-tickrotor exists after all.
Flot sizes it's canvas within the placeholder div to leave enough room for the labels. By rotating them through CSS you are 1.) rotating around the center of the div (hence they go into the canvas area - hint you'll need to shift them down) and 2.) you are overflowing the div container (hint - you'll need to exapand the parent placeholder div). The example you link to works because the text is wrapped and about the same size rotated or not rotated.
Now, the flot-tickrotor deals with these by hooking the low level code of flot and resizing the canvas to make room for the rotated labels (it also gets rid of the label divs and draws the labels using the canvas - which helps with old IE).
So if you really want to pursue rotating the labels yourself, study the code to the plugin and have fun recreating it's functionality.
EDITS
Here's an attempt to use your CSS and make some on the fly adjustments so things will fit:
// push the labels down half their width
// while we are at it find longest label height
var longest = -1;
$('#flot_chart .xAxis .tickLabel').each(function(){
var self = $(this);
var width = self.width();
self.css('top',parseInt(self.css('top')) + width/2 - 5);
if (width > longest){
longest = width;
}
});
// now adjust the chart height so we don't overflow
$("#flot_chart").height($("#flot_chart").height() + longest - $('#flot_chart .xAxis .tickLabel').height() + 5);
See fiddle demonstration here.
Give Padding Bottom and position relative to your main container.
And, give position absolute to your labels and give bottom 0px.
like,
.main-container { padding-bottom:50px; position:relative; }
and
#flot_chart div.xAxis div.tickLabel
{
position:absolute;
bottom:0px;
transform: rotate(-90deg);
-ms-transform:rotate(-90deg); /* IE 9 */
-moz-transform:rotate(-90deg); /* Firefox */
-webkit-transform:rotate(-90deg); /* Safari and Chrome */
-o-transform:rotate(-90deg); /* Opera */
/*rotation-point:50% 50%;*/ /* CSS3 */
/*rotation:270deg;*/ /* CSS3 */
}
I hope this will solve your issue.
If not, than please show your full code via Jsfiddle.
This is a very old question still posting my experience.
I too faced the same issue so I started a trial and error and found that if the max-width is set to a lower value it works fine.
Below is the css that fixed the issue for me (in addition to the the one mentioned in the question).
300 is the max height of the graph I am using,
the max width being set earlier was 71px
#flot-placeholder div.xAxis div.tickLabel {
max-width : 30px !important;
top: 300px !important;
}

Scaling input boxes with -webkit-transform

I applied the following CSS transform to an HTML input box.
-webkit-transform: scale(.5);
When I type text into the input box until it has filled the visible area, the caret continues past the edge of the input and is hidden. Normally the caret and the text would scroll as you type.
The text does eventually start scrolling once the caret has gone the width of the pre-scaled input. The browser seems to be ignoring the scaling when calculating when to scroll the text.
This is only an issue with WebKit browsers (tested with Chrome and iPad). The -moz-transform equivalent works fine in FireFox. The zoom property works fine in webkit, but it isn't nearly smooth enough when scaling on the iPad, so I can't really use it for my project.
You can see an example here: http://jsfiddle.net/4Kv6w/
The first input box is with the -webkit-transform scaling. The second box is with zoom set. The third is normal.
Any help would be greatly appreciated.
EDIT - You can also get the problem without scaling, by using -webkit-transform to move the input box to the left. Here's an example: http://jsfiddle.net/4Kv6w/15/
It seems there is a bug in WebKit when using a CSS transform to move an input box to the left. When you scale down an input box, it essentially moves the right edge to the left, which is how I was experiencing the problem.
The workaround for me was to position the input box way to the left
left: -2000px;
position: absolute;
and then move it back with the CSS transform.
-webkit-transform: matrix(.5, 0, 0, .5, 2000, 0);
You can see an example here: http://jsfiddle.net/4Kv6w/17/
Hey I'm assuming you're trying to animate the change. You will probably have better results using CSS transitions instead of a transform if that's the case. I've created a fiddle for you to see and try it out for yourself.
jsfiddle
Basically, I have a js event listener listening for when the textbox gets focus. Then I change the width in the js and the transition takes care of the animation. Hopefully this takes care of your issue.

Resources