Gradient ends are blurry when using pixel measurements - css

I'm using the background-image: linear-gradient css property to create multiple color strips for a site background.
Usually gradient stops are defined by percentage, but I needed pixels in my site, so I managed to change it to pixels using the method lea Verou used in her patterns
The problem is that the end of each color is a bit blurry. In Firefox it's less noticeable, but in Chrome it's very noticeable.
Is there a way to handle it?
I noticed that when I change the 'deg' from 180 to 45 the ends look great. But unfortunately I need the stripes to be horizontal :)
My code: http://cssdesk.com/c6mGM

Almost a year later and I run into the same bug in chrome v36. I produced a work around here: http://codepen.io/davidgailey/pen/ncrKB
or here if you prefer:
https://gist.github.com/davidgailey/8fc1bd1a09747429a3ad
The work around uses background-size, background-position, and linear gradients.
background-size: 100% 150px, 100% 150px;
background-position: 0 0, 0 bottom;
background-image:
linear-gradient(#000,#000),
linear-gradient(green, green);
Viola! nice crisp horizontal stripes. It could use some work to be more future-friendly.
I hope this bug is fixed soon but in the mean time, feel free to use my pen as a start.

Related

Grid background using 2 linear-gradients doesn't seem to have consistent "thickness" in lines (CSS)

I made a grid background for one element using 2 linear gradients. The lines however don't have consistent thickness and appear blurry in some segments, very clear in others, etc. - see this screenshot:FF screenshot.
The actual CSS for the background looks as follows:
background-image: linear-gradient(to right, black 1px, transparent 0%),
linear-gradient(to bottom, black 1px, transparent 0%);
background-size: 22px 22px;
background-repeat: repeat;
A JS script automatically scales the element's width and height to multiples of 22px based on the available space.
I tried to modify the gradient a bit in terms of size and line width, and with those two being comparatively large everything seems to be fine. But that's not what I want. I also tried using an image I made in Paint3D, but it didn't change anything.
I turned to other browsers, and different engines seem to render it in a different manner, but the problem still persists in one way or another (the above screenshot is FF). It appears as though this is an issue with the rendering itself, and needless to say I have no idea what I could do.
I thank in advance for any suggestions on how to fix this problem.

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.

How can I get css blending modes to apply to different "layers"

I've got a blueprint that I want to absolutely position divs on top of in order highlight certain rooms.
Using the alpha channel (rgba), I can still see the blueprint's "ink" underneath, but depending on the color saturation the drawing gets obscured.
I know that I can use background-blend-mode: multiply on the div that contains the blueprint in order to get the desired effect, but it applies it to the entire image because I have to specify the color and the image on the same div. This is hard to explain but easy to show, so I mocked it up with paint.net here:
Again, I can get the desired look using background-blend-mode but would apply it to the entire background image. I want the color from a div to multiply everything that is underneath it.
Well, I started off writing this question and found out that it is a browser support issue. I eventually found mix-blend-mode which is what will apply blending modes to everything "underneath" a div/element, unfortunately, Chrome (as of today) doesn't support it. Firefox, however, does. It is possible to turn it on in chrome going to chrome://flags/ and enable "experimental Web Platform features".
I found the following link pretty helpful in general, I just didn't realize that they talk about both background-blend-mode and mix-blend-mode. http://css-tricks.com/basics-css-blend-modes/
Here is a screenshot of it working in firefox:
An alternative is to use background-blend-mode, and play with the background-image properties.
Not a very nice solution, but can get you going before waiting from Chrome next release
.test {
width: 400px;
height: 200px;
background-image: linear-gradient(lightgreen, lightgreen), url(http://i.stack.imgur.com/DfAyW.png);
background-blend-mode: multiply;
background-size: 100px 140px, cover;
background-position: 10px 40px, 0px 0px;
background-repeat: no-repeat;
}
<div class="test"></div>

CSS Deciphering Background shorthand

I need a little help with breaking down someone's shorthand to longhand.
Here's what I've been given:
background: url("img.png") repeat scroll 0 0%, -moz-linear-gradient(#4E4E4E, #1C1C1C) repeat scroll 0 0 transparent;
I've gotten this far:
background-image:url('jAGNPCMaDe9LJ5wqwVhLimg.png');
But the rest is definitely greek to me.
I'm curious about the -moz-linear-gradent(). Is this something all browsers recognize? And I'm guessing the colors in the parenthesis must apply a gradient effect (deducing from -moz-linear-gradient)
And what does "repeat scroll 0 0%" do?
As cimmanon has mentioned, you're actually looking at two backgrounds combined into a single background shorthand declaration. The comma separates the two layers. This combination of multiple backgrounds is new to CSS3. So, you have two distinct background layers in shorthand notation:
url("img.png") repeat scroll 0 0%
-moz-linear-gradient(#4E4E4E, #1C1C1C) repeat scroll 0 0 transparent
And each expands to its own set of values.
The correct longhand expansion of your code is this:
background-image: url("img.png"), -moz-linear-gradient(#4E4E4E, #1C1C1C);
background-repeat: repeat, repeat;
background-attachment: scroll, scroll;
background-position: 0 0%, 0 0;
background-color: transparent;
Notice that, again, commas are used to separate multiple background layers. There is only one background-color because you cannot have multiple background colors.
Also as mentioned, the -moz- prefix is Mozilla's vendor extension used for its experimental implementation of linear gradients. However, unless your background declaration is repeated for all other applicable vendor extensions, your code will only work in Mozilla browsers and no other browser because of the vendor extension.
Note also that if you use the longhand code above instead of the shorthand, unsupporting browsers will only ignore the background-image declaration and apply everything else, unlike the shorthand which unsupporting browsers will ignore completely.
You're actually looking at multiple backgrounds there. The comma is the separator.
url("img.png") repeat scroll 0 0% /* on top */
-moz-linear-gradient(#4E4E4E, #1C1C1C) repeat scroll 0 0 transparent /* on bottom */
The gradient is taking the spot of the background image. The rest should be easy to figure out by reading up on the background property.
https://developer.mozilla.org/en-US/docs/CSS/background
Take a look at the Mozilla reference here and the main section here. These should provide you with a good "way in" and an explanation of the -moz-XXX prefix.
here's your longhand:
#element{
background-image:url(img.png);
background-repeat:repeat;
background-attachment:scroll;
background-position:0 0;
background-color:transparent
background-image:-moz-linear-gradient(#4E4E4E, #1C1C1C);
}
The -moz-linear-gradient only works in Mozilla. That is why it is pre-fixed with -moz-. As you guessed right it makes a linear gradient as background, instead of the picture. But only in Mozilla, all other browsers use the background rules. The options of the gradient don't need to be repeated, because they are the same as for every other browser.

Firefox background-image bug

My Firefox is acting weird. I use a simple 4x4px transparent PNG for a div background (as usual). In Chrome, Safari, Opera and even IE it looks great but in FF it's "broken". Here is a picture to show you what I'm talking about: http://cl.ly/2Q1l0S1u3I2Z1e3U2n0G.
I use image and gradient for the background but if I only used the image, it causes the same result.
Here is the code:
#wrap {
background-color: #f5f5f5;
background-image: url(../images/general/bg-wrap.png);
background-image: url(../images/general/bg-wrap.png), -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#ebebeb));
background-image: url(../images/general/bg-wrap.png), -moz-linear-gradient(top, #f5f5f5, #ebebeb);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#ebebeb');
background-position: 0 0; background-repeat: repeat;
}
When I used only the background-image, it looked like this:
#wrap {
background: #f5f5f5 url(../images/general/bg-wrap) 0 0 repeat;
}
And this is the bg-wrap.png: http://cl.ly/0i3i1R0P2R0i1K1h1V1P. I don't understand what's going on...
Everyone's right about the Firefox bug and background image tile dimensions -- I was having the identical problem with a tile that was 16p x 16px. Nealio's answer seems to be correct, but it's not a question of resolution. Rather, take your tile and literally duplicate it so it repeats itself horizontally and vertically, and then use that tile as your background image.
For example, my background image is a simple tile of a very small "checkerboard" with alternating gray and white squares. The first image was the bare minimum to tile the pattern infinitely, so each "checker" measured 8px x 8px, resulting in a background image of 16px x 16px. This looks fine everywhere except Firefox, where it displays the same zig zaggy jaggy rendering as yours did.
After reading Nealio's response, I took that first pattern tile and doubled it so that it was 4 checkers x 4 checkers (8px X 4 = 32).
And voila! Same background appearance, but just a slightly larger tile.
The only thing I can think of is that a number of years ago, early versions of Firefox had trouble repeating background images that were too small (less than about 16x16).
Perhaps this is a new incarnation of that bug when combined with a gradient fill css..?
Just rule this out by testing it with a larger background image.
That is weird...
I set up a fiddle, and it works fine like this: http://jsfiddle.net/will/KMVvT/
Do you think it could be something else interfering?
You should not seperate the mozilla and webkit features with a comma after the closing bracket. Also the image path should be encapsuled within quotes.
I had the problem, that the image was not displayed, but could be viewed with in FireBug. The reason was the adblock plus extension. After disabling for that page (or general) it was displayed, again.

Resources