Chrome leaves white space/gap in between when rendering multiple gradients
Asked Answered
P

1

5

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?

enter image description here

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>
Potemkin answered 22/10, 2016 at 12:23 Comment(0)
H
10

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 :)

Horvath answered 22/10, 2016 at 13:13 Comment(4)
Just as a side note, I remember looking at this example from Lea Verou when she posted it, and back then It rendered ok in Chrome. Probably the rounding in some ancient versions of Chrome was different.Mun
It could well have been @vals. I've been seeing this issue atleast since v43 (had to work with that outdated version for a long time in office :D). Or maybe Lea's demo had a different font-size (and so different calculated value for em).Horvath
Thank you. This is very interesting issue that expand knowledge abaut no only CSS, but also about how browsers rendering it.Potemkin
Thank you. In my case it wasn't crucial to have a small gap between two gradient-filled items, but it's better not to have it on any browser, so this was really helpful.Colombi

© 2022 - 2024 — McMap. All rights reserved.