Is it possible to achieve Retina-quality CSS masking using -webkit-mask-box-image? In this particular case, I am trying to round the corners of an element (border-radius is not performant enough):
.element {
-webkit-mask-box-image: url('mask.png') 12 12 12 12 stretch stretch;
}
The mask image is twice the size that it needs to be (6 is used in place of 12 for non-retina screens).
The mask is correctly positioned, but the corner rounding is not Retina-smooth.
I see three solutions, here:
Suck it up and deal with border-radius, because you can't be getting that much lag on modern machines. Plus, only Safari and Chrome (and minor webkit-based browsers like RockMelt,
Yandex, et cetera) use -webkit-mask, so unless you're making a Chrome app, you're losing a lot of your audience (currently about 54.25%) to browser incompatibility, not to mention that it requires the user to download an image just to see rounded corners.
Webkit uses image smoothing within its scaling algorithm, so simply provide a gigantic mask image and let it do its one-time scaling on load. This has the inherent downside of taking much longer to download and some time after to scale, but, again, it's a one-time thing until the cache clears.
Instead of using a PNG, use an SVG. The whole point of Scalable Vector Graphics is that they're infinitely scalable and don't lose quality at any resolution or size. For more on how to make a SVG file, see http://www.w3.org/Graphics/SVG/
Related
I have a div that uses:
-webkit-clip-path: polygon(0 0, 100% 7%, 100% 100%, 0 100%);
clip-path: polygon(0 0, 100% 7%, 100% 100%, 0 100%);
And there is an image inside this div inside another div. Is there a reason why this specific code causes chrome performance to drop - scrolling becomes choppy too. In Firefox everything looks normal.
Strangely enough, it only affects scrolling when view is on that element, once you scroll past it looks fine again
Clip-Path GPU Rendering
clip-path uses the GPU for rendering, so it is likely to be a graphics card/driver issue or that your system was out of resources and unable to render it effectively.
Try viewing on other machines to see if the same problem exists.
To understand the performance issues and how to debug them these articles will help
Debugging a Canvas Element
Chrome allows you to profile and debug canvas elements from the
Developer Tools. It can be used for both 2D and WebGL canvas projects.
To be able to do this, you need to have enabled the "Experiments" tab.
If you haven't already, navigate to chrome://flags and enable the
option marked "Enable Developer Tools experiments". You'll need to
press "Relaunch Now" button at the bottom of the page to apply your
changes. Go to the Settings panel of Chrome Developer Tools by
clicking the cog on the bottom right. Click the "Experiments" tab and
check the option "Canvas inspection".
Now visit the "Profile" tab and you will see an option called "Capture
Canvas Frame". The Developer Tools may ask you to Reload the page to
use the canvas. Pressing "Start" captures a single frame of the canvas
application. Alternatively, you can click the box below to switch to
"Consecutive Frames" which allows for capture of multiple frames.
Chrome creates a log of each call to canvas, providing a list of each
call to the context and a screenshot. You can click one of the log
items to replay the frame in the Developer Tools and see which
commands were called in the order they were called and from which
line.
Firefox has Canvas and WebGL Shader debugger, giving you features to
inspect frames, fps, modify shaders and more.
In order to enable these tools, go to Devtools settings (the cog icon
in devtools) and check "Canvas" and "Shader Editor".
Picking Your Properties
Animation is not selecting a syntax, it’s designing the animation for
fast rendering. The difference between a smooth, life-like animation
and a janky, stuttery one is rarely as simple as CSS versus
JavaScript. Instead, it’s often determined by which properties or
attributes you animate, on which elements.
Regardless of whether you’re changing a style property with CSS or
with SMIL or with JavaScript, the browser needs to determine which
pixels on the screen need to be updated, and how.
If the DOM and style computation steps determine that no styles or SVG
rendering attributes have changed for any elements, the browser can
stop right there.
If the changed styles don’t affect layout (only painting), or if
layout has changed for some elements but not for others, the browser
has to determine which parts it needs to repaint. This region is known
as the “dirty” rectangle of the screen. Elements elsewhere on the
screen can be skipped, their pixels unchanged for this update.
The changed element usually needs to be repainted, but also maybe
others. Did the changed element overlap another element, which is now
revealed? If so, the browser may need to redraw that background
element.
But maybe not.
It depends on whether the browser has the original pixel data for the
background saved in memory. The graphical processing units (GPU) in
most modern computers and smartphones can keep a certain number of
rendering layers in memory, not just the final version that appears on
screen. The main browser program may also save partial images in
memory.
Much of browser rendering optimization comes down to how it selects
which parts of the rendered document to divide into separately cached
(saved) layers.
GPUs can perform certain operations on the cached rendering layers,
and are highly optimized for the limited number of operations they can
do.
If browsers know that an element is going to change in a way that can
be efficiently calculated by the GPU, they can save that image’s pixel
data in a different GPU layer from its background (or foreground). The
animated changes can therefore be applied by sending new instructions
to the GPU for how to combine the saved pixels, instead of by
calculating new pixel values in the main processor.
Tip Most browser Dev Tools now have options to highlight the “dirty”
paint rectangles whenever they are updated. If your animation is being
GPU-optimized, you won’t see any colored rectangles flashing when you
run this Dev Tools mode.
Of course, all GPU-optimized pathways are conditional on having a
compatible GPU available—and on the browser knowing how to use it,
which may depend on the operating system. So browser performance, and
sometimes even browser bugs, will depend not just on the browser
version but also on the OS and hardware.
Most GPUs can adjust opacity of the saved layers, and translate them
to different relative positions before combining them. They can also
perform image scaling, usually including 3D perspective scaling—but
the scaling is calculated on a pixel level, not a vector level, and
can cause a visible loss in resolution. More advanced GPUs can
calculate some filter operations and blend modes, and masking of one
image layer with an alpha mask layer.
Some GPUs also have optimized vector rasterization, which can
calculate high-resolution vector shapes for use as clipping paths of
other vector levels. These “clipping paths” aren’t only used for
clip-path effects, though. Filling and stroking a shape is clipping
the paint image layer to the fill-region or stroke-region vector
outline. Similarly, CSS border-radius effects are vector clipping
paths on the content and background image layers.
But you currently can’t rely on your end users having these optimized
pathways.
The best performance, across a wide range of browsers and hardwares,
comes from animations that can be broken into layers (of elements,
groups, or individual graphics) that are animated in the
following ways:
opacity changes
translational and rotational transformations
Warning Currently, Chrome never divides an SVG graphic into different
GPU layers (although they do other optimizations).
To create a fully GPU-optimized animation in Chrome, you can sometimes
position separate inline elements over top of each other,
creating your own layers.
If you can’t define your animation entirely in translation and opacity
layers, consider the following guidelines:
Minimize the size of the “dirty” rectangle at each frame.
Solid-color objects are better than semi-transparent ones, since the
browser doesn’t need to calculate pixel updates for shapes that can’t
be seen behind a solid object. (Although this may not apply if the
browser is using GPU layers for optimization.)
Moving elements around is more efficient than changing what they look
like. (Although it depends on the browser whether “moving around” only
applies to transform movements or also to other absolute position
changes.)
Changing fill and stroke is more efficient than changing shapes and
sizes.
Scaling transformations are better than changing the underlying
geometry; browsers may be able to use GPU image scaling for an
animated scale effect, instead of recalculating the vector image at
the correct resolution at each frame.
Clipping is usually more efficient than masking.
Avoid rescaling gradient and pattern layers; this could mean using
user-space effects instead of bounding-box effects, if the bounding
box is changing.
Avoid any changes that require a filter to be recalculated. That
includes any change to the filtered element or its child content.
I've been experimenting with pretty complicated SVG backgrounds (via CSS, fixed, 100% size) and it makes both FF and Webkit based browsers slow to a crawl, to the point it's impossible to scroll.
Would you have any idea how to improve the speed of it?
I investigated a big PNG (slow to load, not as "smooth" as SVG) and Canvas without much success.
The site in question was here. Now it incorporates canvas method.
All the elements on the site are vector-based so it can scale to whatever device there is.
So it seems that all popular browsers render page/scroll much faster when the complicated svg background is applied to an underlying canvas (or img) then if it was applied to the body element itself.
Still looking for suggestions how to make it work faster, but at least now it is usable.
This background is very complicated to render on the fly, so I believe that SVG is not feasible. You will have to consider one of the following solutions:
Use a pre-rendered background (i.e. a png background).
Use a simpler SVG, with less elements. In your current background the browser will have to render each line individually.
Let me start off by stating that I realize the arguments against doing CSS Sprites for large images. I even asked a question about why that could be considered a bad idea (and added an answer of my own). Now that we've had that talk...
I'm going to be making a large CSS Sprite-map. For the process of making this sprite-map, it behooves me to know what (if any) limit exists for the height and/or width of a sprite image in order for browsers to properly process it.
The ultimate reason behind this question is a debate over whether to lay out the sprite images in a grid or in a single row/column. For example: is it necessary or beneficial to do 4000 x 3000 instead of 400 x 30000?
Edit: The sticking point here isn't about what size images can be, but rather what size browsers can process for sprites. Given the lack of detail thus far, I'm moving forward with generating the single-large-column sprite. I'll post details of my experiences as an answer once that is complete.
Sometimes it's more of a matter of download time. Since browsers can use multiple connections to download files, a huge image can take longer to download than a few smaller ones.
If your image is so big that it's slowing down page load maybe it's time to consider several smaller sprite images.
Direct-X 9 has a size limit if 4096 pixels, so any Internet Explorer filters applied to these elements will crop them at 4096 pixels.
See: IE display transparency bug on height > 4096px?
In practice, this seems to work with no problems in Firefox 5+, Chrome, and IE7+ for a sprite image of 400x16560.
The potential issues of IE's directx rendering engine failing on images over 4096px do not create problems in IE7 or beyond; we have no method or need to test IE6 for our current project.
The one place that we experienced problems with really large spritemaps is on mobile platforms. Android devices handle them reasonably well, but iOS devices break down pretty badly, and in a strange way: They shrink the image down to fit within the dimensions they accept. So our CSS works perfectly for a small spritemap, but with no changes except increasing the physical dimensions of the spritemap image, the sprited images begin to show four times as much of the spritemap in the same html entity, with exactly the same CSS.
There is a limit in version 1.0 that is upgraded in v1.1 But still there is a limit for dimensions:
In accord with version 1.1, the scope of the 31-bit limit on chunk
lengths and image dimensions has been extended to apply to all
four-byte unsigned integers. The value -231 is not allowed in signed
integers.
Source
A funny limit is IE6.0 fails to display PNG images of 4097 or 4098 bytes in size!
But these limits are very huge in compare to what we're using in web pages.
It's often stated that when tiling the background of a web page with background-image, that performance is better with an image of larger dimensions due to it needing to be tiled less frequently. For a while I've been making them 8x8 px, or multiples of 8.
But does anyone have links to data that prove this is the case across a range of browsers, taking in rendering times, or CPU load at various points of page rendering?
I'd imagine it matters very little in these modern browsers you listed in your comment:
IE 8/9, and latest versions of
Firefox/Safari/Chome/Opera
However, I have heard of a bug in IE8 when it comes to an image of exactly the size 1px * 1px:
Internet Explorer 8 doesn't perform
the repeat of a 1x1 pixel
semi-transparent background image
correctly when any other element on
the page is using the "-ms-filter"
drective for the alpha transparency:
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
See: http://nemesisdesign.net/blog/coding/ie8-1x1px-semi-transparent-background-bug/
and the demo: http://static.nemesisdesign.net/demos/ie9-1x1px-semi-transparent-background/
So, 8x8 seems like a good enough size to use. I'd be surprised if anyone on the Internets has cared enough about this to rigorously benchmark it.
I did find this, which discusses the subject:
http://blogs.adobe.com/dreamweaver/2011/02/optimal-css-tiled-background-image-size.html
Make sure to also read the comments.
To sum it up, I'm going to quote myself from months ago:
I'd imagine it matters very little in [the] modern browsers [IE 8/9, and latest versions of Firefox/Safari/Chome/Opera] you listed
in your comment.
In some email clients the image won't repeat unless the background image is at least 25X25 so I've settled on that as my default size.
I don't think there is an "optimum size," but the general opinion is that larger dimensions are better than small: see this question, and this one too.
I have a conceptual question about photo galleries like this:
http://www.nikesh.me/demo/image-hover.html
If you open this in a browser that supports CSS Transitions (for example Chrome), it will smoothly scale the hovered image whilst the zoomed version remains of a high quality.
This is accomplished by showing the non-zoomed images into a slightly smaller version than they really are, in essence the zoom shows them in their true dimensions.
So, normal images are first scaled down:
-webkit-transform:scale(0.8);
And then upon hover scaled up:
-webkit-transform:scale(1.2);
My question: How is the initial scaling down supposed to work for browsers that do not support this method of scaling down? Try opening that gallery in IE to see what I mean, it shows the images not scaled down, which makes them too large and thereby they break the layout.
What I want:
The full effect in browsers that support it. Important is that the zoomed version remains quality.
No effect at all for browsers that do not support it, yet a solid original dimension so that no layout is broken
It should work for both image orientations and there may be variety in image widths and heights too
Anyone? Preferably an elegant solution that does not need browser sniffing or javascript, but all answers are welcome.
If you are wanting it to work without the use of javascript then it seems the only method you have is to forgo the initial scale down with css. You will want to do this in the "antiquated" way of adjusting the width and height of the image in the markup.
<img src="yourImageSrc" width="80%" height="80%">
This would allow you to still keep your layout in tact if the user agent is not up to date.
** I don't know if the percentage works in the literal height/width definition. But you can always figure out the ratio you need and plug it in.