498

ok say the content inside the <body> totals 300px high.

If I set the background of my <body> using -webkit-gradient or -moz-linear-gradient

Then I maximize my window (or just make it taller than 300px) the gradient will be exactly 300px tall (the height of the content) and just repeat to fill the rest of the window.

I am assuming this is not a bug since it is the same in both webkit and gecko.

But is there a way to make the gradient stretch to fill the window instead of repeat?

apaderno
  • 28,547
  • 16
  • 75
  • 90
JD Isaacks
  • 56,088
  • 93
  • 276
  • 422

13 Answers13

835

Apply the following CSS:

html {
    height: 100%;
}
body {
    height: 100%;
    margin: 0;
    background-repeat: no-repeat;
    background-attachment: fixed;
}

Edit: Added margin: 0; to body declaration per comments (Martin).

Edit: Added background-attachment: fixed; to body declaration per comments (Johe Green).

Community
  • 1
  • 1
Bryan Downing
  • 15,194
  • 3
  • 39
  • 60
  • 4
    I also found out that I needed to add `margin:0;` on `body` or else I got a gap at the bottom of my page. – Martin at Mennt Dec 15 '10 at 12:18
  • Interesting. What browser? You may want to use a CSS reset. – Bryan Downing Dec 16 '10 at 20:36
  • 9
    In Chrome and Safari, body { height: 100% } results in the page (but not the gradient) extending down out of the viewport. – thSoft Dec 17 '10 at 10:46
  • @thSoft - Add `margin: 0;` to the body declaration as @Martin stated. I was able to verify this fix for Chrome 8 on Win XP. – Bryan Downing Dec 17 '10 at 22:07
  • thank you for this! I was having to add an extra div as a background layer to get this working for me before I read this. – Tony Lukasavage Apr 27 '11 at 13:41
  • 13
    I had to add a background-attachment: fixed; to the body to get rid of the bottom gap (Webkit). – j7nn7k Sep 20 '11 at 11:19
  • 1
    background-attachment:fixed is fine unless you're using the background gradient to divide elements using the background gradient. I, for one, want the background gradient to be a visual divider between the header and the rest of my page, and with the background-attachment:fixed I have the header divider at the top of the page, even when I scroll down – Jon Mitten Mar 06 '12 at 23:21
  • 2
    @JonMitten - That application is somewhat out of the scope of this question. It sounds like you should be applying your gradient to a fixed height container surrounding your header instead of the body. In which case, you would not need to worry about the `height: 100%` declarations on `html` and `body`. All you should need is `background-repeat: no-repeat;` on the container. – Bryan Downing Mar 07 '12 at 00:53
  • @BryanDowning - Yes, indeed. Making a wrapper div inside the body has alleviated that issue, and the gradient goes all the way to the nth pixel, regardless of page height. However, I needed to create a top-level div, because my original top-level div had auto margins left and right, and the gradient would stop at the margins, leaving blank space to the left and right. – Jon Mitten Mar 08 '12 at 00:19
  • 4
    Setting a background to the body and then the height of the html tag to 100% does weird things in Internet Explorer. [Here's an example (png).](http://i.imgur.com/Efruc.png) – Justin Force May 11 '12 at 17:01
  • 24
    Make sure that `background-repeat` and `background-attachment` come _after_ your `background` rules. Otherwise, the background might still repeat. – kellen Feb 06 '14 at 04:09
  • 2
    @kellen - Good point, I would add that you must ensure `background-repeat` and `background-attachment` are defined in a selector with high enough specificity to beat any other `background` declarations. – Bryan Downing Feb 06 '14 at 08:27
  • Be sure to place these rules **AFTER** your gradient rules so they take precedence! – doublejosh Sep 22 '15 at 00:40
  • I've no idea how this works but it works and I won't question that – mark mark May 21 '20 at 22:45
  • I have a page that's taller than the viewport, so setting `height: 100%` means that it resets after you scroll down enough. This solution doesn't fix that unfortunately. – Bobdabiulder Feb 08 '21 at 05:56
  • Just make sure you don't add background like below after following the above code `html, body { background: -webkit-gradient(linear, left top, left bottom, from(#7e57c2), to(#48c2c57b)) fixed !important }` This will apply background twice, first to the body and then to the html tag as well. I made this mistake, hence sharing here. – Ankit Chauhan May 11 '22 at 13:58
182

Regarding a previous answer, setting html and body to height: 100% doesn't seem to work if the content needs to scroll. Adding fixed to the background seems to fix that - no need for height: 100%;

E.g.:

body {
  background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#cbccc8)) fixed;
}
Ruslan López
  • 4,433
  • 2
  • 26
  • 37
Joshua Rudd
  • 1,821
  • 1
  • 11
  • 2
  • 8
    This worked for me in every browser I tested (Chrome [Mac], Safari [Mac], Firefox [Mac/Win7], IE9 [Win7] and Opera [Mac]) without the scrollbar side effect of the "height: 100%" solution. Thanks! – pipwerks May 09 '11 at 17:11
  • 7
    A note for those people using Sass/Compass. You can't set "fixed" directly in the mixin so to add fixed you add the property `background-attachment: fixed` – Kyle Mathews Sep 03 '11 at 20:11
  • 3
    If you want to have either the background fill the window, or the content (whichever is greater) then use `min-height:100%` (in compatible browsers) – cjk May 07 '13 at 09:58
  • I was able to execute the following code using Compass: @include background(linear-gradient(top, red 0%, blue 100%) fixed); – mcranston18 Jun 19 '13 at 16:37
  • How would I add a third color? – sbaden Oct 05 '16 at 19:47
45

I know I'm late to the party, but here's a more solid answer.

All you need to do is use min-height: 100%; rather than height: 100%; and your gradient background will extend the entire height of the content without repeating, even if the content is scrollable.

Like this:

html {
    min-height: 100%;
}

body {
    background: linear-gradient(#b5e48c, #457b9d);
}

There's a second solution though.

As others have said, adding the value fixed to the background declaration, will make the gradient extend the full height of the viewport.

Like this:

body {
    background: linear-gradient(#b5e48c, #457b9d) fixed;
}

Granted, you still need to declare min-height: 100%; in the html.

Here's a demo in CodePen where you can play with both solutions: https://codepen.io/ricardozea/pen/abwGBmz?editors=1100

Ricardo Zea
  • 10,053
  • 13
  • 76
  • 79
15

Here's what I did to solve this problem... it will show the gradient for the full length of the content, then simply fallback to the background color (normally the last color in the gradient).

   html {
     background: #cbccc8;
   }
   body {
     background-repeat: no-repeat;
     background: #cbccc8;
     background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#cbccc8));
     background: -moz-linear-gradient(top, #fff, #cbccc8);
     filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#cbccc8');
   }
<body>
  <h1>Hello world!</h1>
</body>

I've tested this in FireFox 3.6, Safari 4, and Chrome, I keep the background-color in the body for any browsers that for some reason don't support styling the HTML tag.

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
John Sanford
  • 159
  • 3
14

Setting html { height: 100%} can wreak havoc with IE. Here's an example (png). But you know what works great? Just set your background on the <html> tag.

html {
  -moz-linear-gradient(top, #fff, #000);
  /* etc. */
}

Background extends to the bottom and no weird scrolling behavior occurs. You can skip all of the other fixes. And this is broadly supported. I haven't found a browser that doesn't let you apply a background to the html tag. It's perfectly valid CSS and has been for a while. :)

Justin Force
  • 6,203
  • 5
  • 29
  • 39
  • 1
    @Lynda That's not very helpful feedback. Would you mind providing a case where it doesn't work? – Justin Force Oct 05 '15 at 19:00
  • Sorry for being vague. I am unsure why it doesn't work. You can add a gradient to `html` but it stops part way down the page in my case. Adding `background-attachment:fixed` does solve the issue. I've seen this happen on more than one site but haven't been able to find the cause. – L84 Oct 05 '15 at 19:17
  • The point of this solution is that it worked across browsers (in 2012, by the way). But you still don't indicate what browser you're talking about. If you're still having trouble, try adding `html, body { height: 100%; }`. – Justin Force Oct 06 '15 at 17:36
  • True. It happens in Firefox and Chrome (didn't test in other browsers) and I tried height and various other settings without any luck (except background-attachment). Oh well, not a big deal and hopefully your answer still works for most. => – L84 Oct 06 '15 at 22:38
  • Still have to fool with no-repeat and fixed. – Kalnode Aug 06 '18 at 00:14
12

There is a lot of partial information on this page, but not a complete one. Here is what I do:

  1. Create a gradient here: http://www.colorzilla.com/gradient-editor/
  2. Set gradient on HTML instead of BODY.
  3. Fix the background on HTML with "background-attachment: fixed;"
  4. Turn off the top and bottom margins on BODY
  5. (optional) I usually create a <DIV id='container'> that I put all of my content in

Here is an example:

html {  
  background: #a9e4f7; /* Old browsers */
  background: -moz-linear-gradient(-45deg,  #a9e4f7 0%, #0fb4e7 100%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#a9e4f7), color-stop(100%,#0fb4e7)); /* Chrome,Safari4+ */ 
  background: -webkit-linear-gradient(-45deg,  #a9e4f7 0%,#0fb4e7 100%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(-45deg,  #a9e4f7 0%,#0fb4e7 100%); /* Opera 11.10+ */
  background: -ms-linear-gradient(-45deg,  #a9e4f7 0%,#0fb4e7 100%); /* IE10+ */
  background: linear-gradient(135deg,  #a9e4f7 0%,#0fb4e7 100%); /* W3C */ 
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a9e4f7', endColorstr='#0fb4e7',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */

  background-attachment: fixed;
}

body {
  margin-top: 0px;
  margin-bottom: 0px;
}

/* OPTIONAL: div to store content.  Many of these attributes should be changed to suit your needs */
#container
{
  width: 800px;
  margin: auto;
  background-color: white;
  border: 1px solid gray;
  border-top: none;
  border-bottom: none;
  box-shadow: 3px 0px 20px #333;
  padding: 10px;
}

This has been tested with IE, Chrome, and Firefox on pages of various sizes and scrolling needs.

Rick Smith
  • 9,031
  • 15
  • 81
  • 85
  • 1
    Great! I was using colorzilla and the main answer didn't work for me. This one did. Thank you! :) – Aylen Jan 16 '14 at 15:47
  • Why is your preference to do it on HTML, not on BODY? – sashaikevich Dec 14 '17 at 23:06
  • @sashaikevich Great question. I haven't hardly looked at this answer in 5 years so I don't remember at all. The reason I did it might not even still apply with all of the browser updates. If you moved it all to body, I'd be curious if it worked the same. – Rick Smith Jan 05 '18 at 20:07
  • @RickSmith Nope, I styled html. But, I did move the rules to apply to body just now to check, and that made no difference. Maybe it was an old browser thing... – sashaikevich Jan 05 '18 at 22:18
7

Adding a space and the word fixed to the end should be sufficient. No need to set heights.

body{
    background: linear-gradient(#e4efe9,#93a5cf) fixed;
}
Alan Simpson
  • 447
  • 5
  • 5
  • The "space" between the last parenthesis and the notation `fixed`, is required in the `background` shorthand syntax. So the "space" isn't the solution, but the notation `fixed`. Which it's a different solution because unlike mine above, the gradient background extends the height of the **viewport**, whereas mine, extends the height of the **content**. I think this is a great solution as well. – Ricardo Zea Nov 27 '21 at 06:54
  • Actually, I take that back, the space between the last parenthesis and the notation `fixed` is NOT required. – Ricardo Zea Nov 27 '21 at 07:38
  • This should be the accepted answer. – Abdelfattah Radwan Mar 06 '22 at 02:45
4

Dirty; maybe could you just add a min-height: 100%; to the html, and body tags? That or at least set a default background color that is the end gradient color as well.

subv3rsion
  • 412
  • 6
  • 14
  • 1
    The default background set as the end gradient color would be a great solution if the gradient stopped, but it doesn't just stop it repeats so the default background would only be seen if the gradient is unsupported. – JD Isaacks May 19 '10 at 21:09
2

I had trouble getting the answers in here to work.
I found it worked better to fix a full-size div in the body, give it a negative z-index, and attach the gradient to it.

<style>

  .fixed-background {
    position:fixed;
    margin-left: auto;
    margin-right: auto;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: -1000;
    background-position: top center;
    background-size: cover;
    background-repeat: no-repeat;
  }

  .blue-gradient-bg {
    background: #134659; /* For browsers that do not support gradients */
    background: -webkit-linear-gradient(top, #134659 , #2b7692); /* For Safari 5.1 to 6.0 */
    background: -o-linear-gradient(bottom, #134659, #2b7692); /* For Opera 11.1 to 12.0 */
    background: -moz-linear-gradient(top, #134659, #2b7692); /* For Firefox 3.6 to 15 */
    background: linear-gradient(to bottom, #134659 , #2b7692); /* Standard syntax */
  }

  body{
    margin: 0;
  }

</style>

<body >
 <div class="fixed-background blue-gradient-bg"></div>
</body>

Here's a full sample https://gist.github.com/morefromalan/8a4f6db5ce43b5240a6ddab611afdc55

morefromalan
  • 302
  • 3
  • 9
0

I have used this CSS code and it worked for me:

html {
  height: 100%;
}
body {
  background: #f6cb4a; /* Old browsers */
  background: -moz-linear-gradient(top, #f2b600 0%, #f6cb4a 100%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f2b600), color-stop(100%,#f6cb4a)); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(top, #f2b600 0%,#f6cb4a 100%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(top, #f2b600 0%,#f6cb4a 100%); /* Opera 11.10+ */
  background: -ms-linear-gradient(top, #f2b600 0%,#f6cb4a 100%); /* IE10+ */
  background: linear-gradient(top, #f2b600 0%,#f6cb4a 100%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f2b600', endColorstr='#f6cb4a',GradientType=0 ); /* IE6-9 */
  height: 100%;
  background-repeat: no-repeat;
  background-attachment: fixed;
  width: 100%;
  background-position: 0px 0px;
}

A related information is that you can create your own great gradients at http://www.colorzilla.com/gradient-editor/

/Sten

Netsi1964
  • 3,244
  • 1
  • 27
  • 17
-1
background: #13486d; /* for non-css3 browsers */
background-image: -webkit-gradient(linear, left top, left bottom, from(#9dc3c3),   to(#13486d));  background: -moz-linear-gradient(top,  #9dc3c3,  #13486d);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#9dc3c3', endColorstr='#13486d');
background-repeat:no-repeat;
edgerunner
  • 14,873
  • 2
  • 57
  • 69
Joe
  • 1
-1

this is what I did:

html, body {
height:100%;
background: #014298 ;
}
body {
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#5c9cf2), color-stop(100%,#014298));
background: -moz-linear-gradient(top, rgba(92,156,242,1) 0%, rgba(1,66,152,1) 100%);
background: -o-linear-gradient(top, #5c9cf2 0%,#014298 100%);

/*I added these codes*/
margin:0;
float:left;
position:relative;
width:100%;
}

before I floated the body, there was a gap on top, and it was showing the background color of html. if I remove the bgcolor of html, when I scroll down, the gradient is cut. so I floated the body and set it's position to relative and the width to 100%. it worked on safari, chrome, firefox, opera, internet expl.. oh wait. :P

what do you guys think?

grizzy
  • 7
  • 2
-4

instead of 100% i just add some pixxel got this now and it works for whole page without gap:

html {     
height: 1420px; } 
body {     
height: 1400px;     
margin: 0;     
background-repeat: no-repeat; }
Brad
  • 159,648
  • 54
  • 349
  • 530
SANDER
  • 1
  • 1