Chrome leaves white space/gap in between when rendering multiple gradients - css

I'm reading book "CSS Secrets" from Lea Verou.
There is example with radial multiple gradients for round corners:
http://dabblet.com/gist/24484257bc6cf7076a8e
IE11, Edge and FF display it correctly as it was intended. But Chrome create strange borders inside of block.
I can't understand why. It's look like a bug. Can anybody explain this behavior, may be this is just a part of Blink specification?
div {
background: #58a;
background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left,
radial-gradient(circle at top right, transparent 15px, #58a 0) top right,
radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right,
radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
width:4em;
height:4em;
padding: 1em 1.2em;
max-width: 12em;
color: white;
font: 130%/1.6 Baskerville, Palatino, serif;
}
<div></div>

I don't have any official sources to back this answer (not as yet, I am trying to find and will add here if I manage to find) but I've seen similar issues in Chrome in the past and they seem to because of how the calculated values are rounded in Chrome. Rounding is being done here because background size is 50% in both X and Y axis and the calculated values for 50% are fractions. The calculation is provided as inline comments within the snippet below.
Blink/WebKit seems to round down the calculated value irrespective of whether it is above 0.5 or not. In this demo, the total height of the element is 124.8px and the width is 133.12px. So, the 50% values become 62.4px and 66.56px (which are getting rounded down to 62 and 66px). The third div in the snippet has these values set explicitly as the background-size and we can see how its output looks same as the first one (which has background-size: 50% 50%) and thereby proving the explanation.
When the values are thus rounded down, the actual area occupied by the background horizontally is 132px (which is 1.12px less than the actual width) and that vertically is 124px (which is 0.8px lesser than the actual height). Thus it leaves a gap in between.
This blog post by John Resig also gives some insight on how rounding is handled in browsers. As we saw, Blink/WebKit is rounding down whereas IE seems to be rounding it up. Rounding up means the calculated values would become 63px and 67px and this wouldn't visibly show any problems because the color on all sides are the same and so they just overlap and fill the space (Chrome also shows no issues when we explicitly set these values for background size - refer second div). Firefox seems to have a comprehensive rounding logic which seems to round up some while some other get rounded down in-order to completely fill space and hence shows no issues too.
div {
background: #58a;
background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left,
radial-gradient(circle at top right, transparent 15px, #58a 0) top right,
radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right,
radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
width:4em; /* 83.2px */
height:4em; /* 83.2px */
padding: 1em 1.2em; /* left/right padding = 24.96px, top padding = 20.8px */
max-width: 12em;
color: white;
font: 130%/1.6 Baskerville, Palatino, serif; /* font-size = 130% of 16px = 20.8px */
}
/* so,
total width = 83.2px + (24.96px * 2) = 133.12px (50% = 66.56px)
total height = 83.2px + (20.8px * 2) = 124.8px (50% = 62.4px)
*/
div:nth-of-type(2) {
background-size: 67px 63px;
}
div:nth-of-type(3) {
background-size: 66px 62px;
}
div{
display: inline-block;
margin: 10px;
}
<div></div>
<div></div>
<div></div>
This is not the case for just radial gradients, it happens with linear gradients also.
div {
background: #58a;
background: linear-gradient(red, red) top left,
linear-gradient(blue, blue) top right,
linear-gradient(green, green) bottom right,
linear-gradient(tomato, tomato) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
width:4em; /* 83.2px */
height:4em; /* 83.2px */
padding: 1em 1.2em; /* left/right padding = 24.96px, top padding = 20.8px */
max-width: 12em;
color: white;
font: 130%/1.6 Baskerville, Palatino, serif; /* font-size = 130% of 16px = 20.8px */
}
/* so,
total width = 83.2px + (24.96px * 2) = 133.12px (50% = 66.56px)
total height = 83.2px + (20.8px * 2) = 124.8px (50% = 62.4px)
*/
div:nth-of-type(2) {
background-size: 67px 63px;
}
div:nth-of-type(3) {
background-size: 66px 62px;
}
div{
display: inline-block;
margin: 10px;
}
<div></div>
<div></div>
<div></div>
And also with images also.
div {
background: #58a;
background: url(http://lorempixel.com/100/100/animals/1) top left,
url(http://lorempixel.com/100/100/animals/2) top right,
url(http://lorempixel.com/100/100/animals/3) bottom right,
url(http://lorempixel.com/100/100/animals/4) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
width:4em; /* 83.2px */
height:4em; /* 83.2px */
padding: 1em 1.2em; /* left/right padding = 24.96px, top padding = 20.8px */
max-width: 12em;
color: white;
font: 130%/1.6 Baskerville, Palatino, serif; /* font-size = 130% of 16px = 20.8px */
}
/* so,
total width = 83.2px + (24.96px * 2) = 133.12px (50% = 66.56px)
total height = 83.2px + (20.8px * 2) = 124.8px (50% = 62.4px)
*/
div:nth-of-type(2) {
background-size: 67px 63px;
}
div:nth-of-type(3) {
background-size: 66px 62px;
}
div{
display: inline-block;
margin: 10px;
}
<div></div>
<div></div>
<div></div>
Note: I've been wanting to post a self Q & A for documenting this behavior for quite sometime now, so thank you for asking :)

Related

background-image repeat pattern is showing side effects when pattern size is small

I am trying to create a table pattern using background image, it works fine when cell size is 50px * 50px but when I go below 25px * 25px few rows start to disappear or get fainted.
What is the reason behind this & how can it be fixed?
At 25px * 25px
At 50px * 50px
div {
background: pink;
height: 713px;
width: 400px;
background-size: 25px 25px;
/*background-size: 50px 50px;*/
background-image: url("https://svgshare.com/i/_GG.svg");
}
<div></div>
codepen: https://codepen.io/arnavsingh/pen/bGWPqXP
Note: It gets fixed when I zoom in using browser settings
such task is now trivial with only one gradient:
div {
background: pink;
height: 713px;
width: 400px;
--b:1px; /* adjust this */
background:
conic-gradient(at bottom var(--b) right var(--b),#000 75%,#0000 0)
0 0/25px 25px /* and this */
pink;
}
<div></div>
Only way i can think of, is to set your widht and height to some math size with variables.
For example your height will be like
height: $someSize * 10; background-size: $someSize $someSize ;
It's probably because the line in your svg can't be rendered at the smaller size (as the border becomes less than 1px).
Why not try using a linear gradient instead (change the 25px for whatever size square you want):
div {
height: 713px;
width: 400px;
background:
repeating-linear-gradient(to right,
transparent 0 calc(25px - 1px),
#AA8087 calc(25px - 1px) 25px),
repeating-linear-gradient(to bottom,
transparent 0 calc(25px - 1px),
#AA8087 calc(25px - 1px) 25px)
#FFC0CB;
}
<div></div>

Hovered background color change breaks simulated + display

I have a button with + and - symbols made with linear gradients and background size. If I add a hover state, just changing the color, the + and - effect doesn't work. Any idea why this happens?
This is the pen: https://codepen.io/miguelrivero/pen/gOraZaM
.AddToBagButton__decrease,
.AddToBagButton__increase {
background: linear-gradient(#2e8561, #2e8561) top left,
linear-gradient(#2e8561, #2e8561) top right,
linear-gradient(#2e8561, #2e8561) bottom left,
linear-gradient(#2e8561, #2e8561) bottom right;
background-repeat: no-repeat;
border: 13px solid #2e8561;
box-sizing: border-box;
border-radius: 50%;
&:hover {
background: linear-gradient(#215e45, #215e45) top left,
linear-gradient(#215e45, #215e45) top right,
linear-gradient(#215e45, #215e45) bottom left,
linear-gradient(#215e45, #215e45) bottom right;
border: 13px solid #215e45;
}
}
.AddToBagButton__decrease {
background-size: 100% calc(50% - .5px);
left: 0;
}
.AddToBagButton__increase {
background-size: calc(50% - 1px) calc(50% - .5px);
right: 0;
}
Any idea why this happens?
Because you are overwriting the background-size you specified for the buttons, by applying the changed gradient via the background shorthand property, which resets all individual background properties you did not specify, to their defaults. (.AddToBagButton__decrease:hover has a higher specificity, than .AddToBagButton__decrease.)
Make that
&:hover {
background-image: …
instead. (Gradients are considered images in CSS.)

How do i turn my triangle responsive?

I'm trying to put my triangle responsive, because it only works on desktop computers, how can i do that?
I have a code here, and i want to turn my div into a responsive div, for mobile phones, tablets...
triangle code:
*{
background-color: black;
padding:0;
margin:0 auto;
}
.triangle-down {
width: 0px;
height: 0px;
border-style: solid;
border-width: 642px 187.5px 0 187.5px;
border-color: #007bff transparent transparent transparent;
}
html code
<div class="triangle-down"></div>
if you do not mind using background-radient, this could be an alternative as body background:.
http://codepen.io/gc-nomade/pen/mBjtC
body {
background:
linear-gradient(
to top left,
black,
black 50%,
rgba(0,0,0,0) 50%,
rgba(0,0,0,0)) top center no-repeat,
linear-gradient(
to top right,
black,
black 50%,
#007bff 50%,
#007bff ) top center no-repeat;
background-size:40% 200%;/* set your own values and units here */
background-color: black;
padding:0;
margin:0 auto;
min-height:100%;
}
html {
height:100%;
}
You should probably use percentages instead of pixels, you can work out the equivalent by dividing the pixel size by the context, which is usually the size of the body container which you haven't declared but is usually 1000px for ease. To use ems, it's divided by the base piel size, or you can use a converter, if you haven't declared a base font size it's usually 16px http://pxtoem.com/

CSS limited background repeat (multiple background images)

I am trying to make a cool background effect (with alpha transparency and rounded corners) for a drop-down menu with a single CSS entry.
I have a top cap (180 x 4 px), a bottom cap (180 x 20px) and a repeating middle (180 x 2px).
Here is my existing relevant CSS:
background-image: url('images/drop_top.png'), url('images/drop_bottom.png'), url('images/drop_middle.png');
background-position:left top, left bottom, 0px 10px;
background-repeat:no-repeat, no-repeat, repeat-y;
The problem is that the middle section which needs to be expandable/tilable is repeating all the way under the top and bottom caps--such that my rounded corners are now square because they have the repeating middle under them.
Is there some way to prevent the multiple backgrounds from overlapping??
Thanks in advance!
Background-origin and/or background-clip should do the trick. Just set top & bottom borders equal to the height of your cap graphics, then set drop_middle to background-clip:padding-box
EDIT: Here is a complete solution, but for a horizontal orientation:
http://jsfiddle.net/nGSba/
#box
{
display: inline-block;
margin: 1em;
padding: 9px;
border-left:9px solid transparent;
border-right:9px solid transparent;
background-image: url(http://s11.postimage.org/ufpdknvjz/left.png),
url(http://s11.postimage.org/6ng294tj3/right.png),
url(http://www.css3.info/wp-content/themes/new_css3/img/main.png);
background-repeat: no-repeat, no-repeat, repeat-x;
background-position: left top, right top, left top;
background-origin: border-box,border-box,padding-box;
background-clip: border-box,border-box,padding-box;
}
What got me stuck was the transparent on the border-color. The background will always go under the border, so if your border is solid the background will still be invisible.
Whatever your element is that you are applying the images to, try doing the following (I'll assume div for sake of illustration):
div {
background-image: url('images/drop_top.png'), url('images/drop_bottom.png');
background-position:left top, left bottom;
background-repeat:no-repeat, no-repeat;
position: relative;
}
div:after {
position: absolute;
top: 10px ; /* whatever your top image height is */
bottom: 10px; /* whatever your bottom image height is */
left: 0;
right: 0;
z-index: -1;
background-image: url('images/drop_middle.png');
background-position: left top;
background-repeat: repeat-y;
}

Can I apply multiple background colors with CSS3?

I know how to specify multiple background images using CSS3 and modify how they are displayed using different options.
Currently I have a <div>, which needs to have a different color for about 30% of the width on the left side:
div#content {
background: url("./gray.png") repeat-y, white;
background-size: 30%;
}
Instead of loading the image which is totally gray, how can I do this specifying the color, and without additional <div>s?
Yes its possible! and you can use as many colors and images as you desire, here is the right way:
body{
/* Its, very important to set the background repeat to: no-repeat */
background-repeat:no-repeat;
background-image:
/* 1) An image */ url(https://placeimg.com/640/100/nature/John3-16),
/* 2) Gradient */ linear-gradient(to right, RGB(0, 0, 0), RGB(255, 255, 255)),
/* 3) Color(using gradient) */ linear-gradient(to right, RGB(110, 175, 233), RGB(110, 175, 233));
background-position:
/* 1) Image position */ 0 0,
/* 2) Gradient position */ 0 100px,
/* 3) Color position */ 0 130px;
background-size:
/* 1) Image size */ 640px 100px,
/* 2) Gradient size */ 100% 30px,
/* 3) Color size */ 100% 30px;
}
You can’t really — background colours apply to the entirely of element backgrounds. Keeps ’em simple.
You could define a CSS gradient with sharp colour boundaries for the background instead, e.g.
background: -webkit-linear-gradient(left, grey, grey 30%, white 30%, white);
But only a few browsers support that at the moment. See http://jsfiddle.net/UES6U/2/
(See also http://www.webkit.org/blog/1424/css3-gradients/ for an explanation CSS3 gradients, including the sharp colour boundary trick.)
You can use as many colors and images as you desire.
Please note that the priority with which the background images are rendered is FILO, the first specified image is on the top layer, the last specified image is on the bottom layer (see the snippet).
#composition {
width: 400px;
height: 200px;
background-image:
linear-gradient(to right, #FF0000, #FF0000), /* gradient 1 as solid color */
linear-gradient(to right, #00FF00, #00FF00), /* gradient 2 as solid color */
linear-gradient(to right, #0000FF, #0000FF), /* gradient 3 as solid color */
url('http://lorempixel.com/400/200/'); /* image */
background-repeat: no-repeat; /* same as no-repeat, no-repeat, no-repeat */
background-position:
0 0, /* gradient 1 */
20px 0, /* gradient 2 */
40px 0, /* gradient 3 */
0 0; /* image position */
background-size:
30px 30px,
30px 30px,
30px 30px,
100% 100%;
}
<div id="composition">
</div>
In this LIVE DEMO i've achieved this by using the :before css selector which seems to work quite nicely.
.myDiv {
position: relative; /*Parent MUST be relative*/
z-index: 9;
background: green;
/*Set width/height of the div in 'parent'*/
width:100px;
height:100px;
}
.myDiv:before {
content: "";
position: absolute;/*set 'child' to be absolute*/
z-index: -1; /*Make this lower so text appears in front*/
/*You can choose to align it left, right, top or bottom here*/
top: 0;
right:0;
bottom: 60%;
left: 0;
background: red;
}
<div class="myDiv">this is my div with multiple colours. It work's with text too!</div>
I thought i would add this as I feel it could work quite well for a percentage bar/visual level of something.
It also means you're not creating multiple divs if you don't have to, and keeps this page up-to-date
You can only use one color but as many images as you want, here is the format:
background: [ <bg-layer> , ]* <final-bg-layer>
<bg-layer> = <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box>{1,2}
<final-bg-layer> = <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box>{1,2} || <background-color>
or
background: url(image1.png) center bottom no-repeat, url(image2.png) left top no-repeat;
If you need more colors, make an image of a solid color and use it. I know it’s not what you want to hear, but I hope it helps.
The format is from http://www.css3.info/preview/multiple-backgrounds/
In case someone needs a CSS background with different color repeating horizontal stripes, here is how I managed to achieve this:
body {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
}
.css-stripes {
margin: 0 auto;
width: 200px;
padding: 100px;
text-align: center;
/* For browsers that do not support gradients */
background-color: #F691FF;
/* Safari 5.1 to 6.0 */
background: -webkit-repeating-linear-gradient(#F691FF, #EC72A8);
/* Opera 11.1 to 12.0 */
background: -o-repeating-linear-gradient(#F691FF, #EC72A8);
/* Firefox 3.6 to 15 */
background: -moz-repeating-linear-gradient(#F691FF, #EC72A8);
/* Standard syntax */
background-image: repeating-linear-gradient(to top, #F691FF, #EC72A8);
background-size: 1px 2px;
}
<div class="css-stripes">Hello World!</div>
JSfiddle

Resources