7

When using linear-gradient CSS property, the background appears without stripes when using left and right as direction value. But when direction value is given as top or bottom, stripes appears in the background. Is there any way that we can remove the stripes?

Here is the code:

body {
  background: linear-gradient(to top, red, yellow);
}
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Bala
  • 163
  • 1
  • 8
  • Can you explain the common things between these questions? I dont understand how they are related. – Bala Jan 29 '18 at 13:50
  • This question might be improved if you could include screenshots of one vs. the other - it's hard to tell by your description what is going on, vs what the desired outcome is. – theMayer Jan 29 '18 at 15:57

2 Answers2

7

You are facing a complex background propagation that you can read about here. I will try to explain it with simple words.

Your body has a height equal to 0; thus the background won't be visible on it but by default it has 8px of margin which create a height of 8px on the html element.


Why not 16px of height (8px for top + 8px for bottom)?

Since the height of body is 0 we are facing a margin collpasing and both margin will collapse into only one and we have a height of 8px.


Then we have a background propagation from body to html and the linear-gradient will cover the 8px height.

Finally, the background of the html is propagated to the canvas element in order to cover the whole area which explain why the linear gradient is repeating each 8px.

body {
  background: linear-gradient(to top, red, yellow);
}

It's also repeated when using left or right direction but you won't see it visually which is logical since it's the same pattern:

body {
  background: linear-gradient(to right, red, yellow);
}

You can also remove the repeating and you will see it's covering only 8px

body {
  background: linear-gradient(to right, red, yellow) no-repeat;
}

In order to avoid this behavior you can simply set height:100% (or min-height:100%) to the html

html {
  height: 100%;
}

body {
  background: linear-gradient(to top, red, yellow);
}

It will also work with no-repeat since by default a linear-gradient will cover the whole are:

html {
  min-height: 100%;
}

body {
  background: linear-gradient(to top, red, yellow) no-repeat;
}
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Ok I seem to get the point. There is an infinite canvas stuff behind everything. The `html` is just like a viewport of that infinite stuff. And if the `html`/document size is for some reasons no big enough to fill the browser window, the rest what I will see is painted on the infinite "canvas" (by propagation). – Rick Sep 25 '19 at 09:21
  • Thanks a lot. But one question: I visited the W3C link in your answer and I looked around. I didn't find any descriptions that saying stuffs like "the `html` would repeats so as to fill the infinite canvas" . – Rick Sep 25 '19 at 09:24
  • @Rick yes and the propagaion only happen if you don't set an explicit background to the html element. Doing so you will stop the propagation from the body to the canvas – Temani Afif Sep 25 '19 at 09:24
  • @Rick it's not the html that would repeat but the background of the html will be used and get repeated. From the spec : *The background of the root element becomes the background of the canvas and its background painting area extends to cover the entire canvas* : not when it says the background of the root become the one of the canvas – Temani Afif Sep 25 '19 at 09:27
  • 1
    @Rick check this example: https://jsfiddle.net/8jv9gxpw/ .. see how the border is only covering the 8px margin for the body and the background is covering the whole area. So the HTML is not filling all the area. Only its background is used to fill that area – Temani Afif Sep 25 '19 at 09:28
  • **"its background painting area extends to cover the entire canvas"** indicates **it will repeat** (obscure as always) ;P. Yes, I know there is only 1 `html` and 1 canvas. Your example is awesome and now makes things clearer. Aagin, many thanks for your patience. – Rick Sep 25 '19 at 09:36
  • 1
    @Rick yes it **will repeat** but only the background will do and not the html as you stated in other comment. The trick is there. The html has a height lower than the canvas, the background of that height will be used and repeated over the canvas. That's why making the height of html equal to canvas (height:100%) will avoid this repeat. – Temani Afif Sep 25 '19 at 09:39
  • Ah yes I knew. I was expressing myself in a hurry. But making `html` 100% doesn't equal to canvas right? I am thinking that the canvas is always infinite and both `html` and what we see in the browser window are only parts of it (you know what I mean ;) ). – Rick Sep 25 '19 at 10:01
  • 1
    @Rick well, it's more tricky if we want to define precisely the canvas. Yes it's infinite as per the sepcification (https://www.w3.org/TR/CSS2/intro.html#the-canvas) but infinite doesn't exist in the real world and there is a defined area where the canvas is painted. In other words, we cannot see beyond the browser so we can say that the browser is somehow the limits of the canvas area we see. This said, if you make the html 100% you will at least be sure it will cover the visual area of the canvas we see but will technically remain different from the canvas – Temani Afif Sep 25 '19 at 10:07
  • Ya that's my point. I have already visited that page while reading your answer. – Rick Sep 25 '19 at 10:12
  • @TemaniAfif When you set the html tag to be 100% as in `html { height: 100% }` What does that mean? I usually understand it as 100% the height of its parent element. – Robert May 10 '21 at 14:18
  • 1
    @RobertRocha it's more precisely the "containing block" rather than the parent element. In most of the case the containing block is the parent element. For the html element it's the *initial containing block* (a special one and its height is the one of the viewport). Related: https://www.w3.org/TR/CSS21/visudet.html#containing-block-details – Temani Afif May 10 '21 at 14:22
2

That's because the calculated height of <body> is resulting from the height of its content. When smaller than viewport's height, the background will repeat itself:

body {
  background: linear-gradient(to top, red, yellow);
}

To make sure it stretches itself (and the background gradient) across the entire height of the viewport, you need to give <body> a min-height equal with viewport's height (100vw):

body {
  background: linear-gradient(to top, red, yellow);
  min-height: 100vh;
}

body {
  background: linear-gradient(to top, red, yellow);
  min-height: 100vh;
  margin: 0;
}

As @TemaniAfif pointed out in comments, the technical reason for the above is: there is a difference between the root element, which covers the entire viewport and inherits its background from <body>, and the <body> element, which, as specified, can be smaller than the viewport. As per W3C Recommendation:

The background of the root element becomes the background of the canvas and covers the entire canvas, anchored (for 'background-position') at the same point as it would be if it was painted only for the root element itself. The root element does not paint this background again.

tao
  • 82,996
  • 16
  • 114
  • 150
  • i guess you should mention that it repeat on the root element because there is background propagation and the root element is full screen height – Temani Afif Jan 29 '18 at 13:42
  • Thank you @andrei. That works fine. – Bala Jan 29 '18 at 13:43
  • and it ls more complex than simple background propagation, am trying to explain it on an answer but not easy :s ... the issue is that the body has margin of 8px which make the height of html 8px and this one take the linear-gradient as background image from the first propagation and thus cover the 8px and then the second propagation to root element keep the same size of the background and simply repeat it and we have this result! ... make the body margin:0 and we will have no more background ! – Temani Afif Jan 29 '18 at 14:17
  • @Temani, I feel my answer is sufficient in terms of technical data. The point was to briefly explain what's going on and provide a practical solution. Not to explain the entire spec. Whoever's interested in more details can find them on either the linked spec or in MDN. – tao Jan 29 '18 at 14:19
  • 1
    am not complaining about your answer ;) as you are not obliged to explain the whole process but i guess it's important for people who are a bit curious like me to clearly understand what's happening even if we can do wihout it. That's why am commenting so that people may find some clue in order to search more about and unrestand. [by the whay doing `html{height:100%}` will also solve the issue] – Temani Afif Jan 29 '18 at 14:25