I'm trying to implement a diagonal CSS3 gradient that goes from black in the upper left corner to dark gray in the bottom right corner.
Something like:
body {
background: -webkit-linear-gradient(left top, black, darkgray 80%, gray);
}
Instead of it being shown as I intended, it just repeats over and over every couple lines down the page horizontally. What am I doing wrong?
The body has no height; you're only seeing the background from the 8px of top/bottom margin (which is always transparent).
If you want your gradient to fill the viewport, set a height of 100% on both <html> & <body>
html, body {
height: 100%;
}
body {
background: linear-gradient(orange, red, yellow);
margin: 0;
}
http://jsfiddle.net/JUtuJ/1/
Related
This question already has answers here:
CSS3 gradient background set on body doesn't stretch but instead repeats?
(13 answers)
Closed 4 years ago.
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);
}
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;
}
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.
I'm struggling to skew a div like the image below... whereby the bottom and top always cover 50% of the screen width if that makes sense.
I have attached an image for more info
EDIT: this is a photoshop image and I'm trying to recreate this with CSS.
I am not sure about the use case, but you can recreate this using 2 linear-gradient. Each one will have a triangle shape and will cover half the container.
body {
margin: 0;
}
.container {
height: 200px;
background:
linear-gradient(to top left, blue 50%,transparent 50.5%) left/50% 100% no-repeat,
linear-gradient(to bottom right, blue 50%,transparent 50.5%) right/50.5% 100% no-repeat;
}
<div class="container">
</div>
I'm stuck on a CSS problem.
I would like to get a CSS stripe as background of my page like i did here, except that i want the stripe to be located on the bottom right corner of the page.
Moreover i want it to be a fixed background attachment.
I tried what is suggested here : How to position background image in bottom right corner? (CSS) but it seems to work only for background images and not for background gradients.
I tried changing offsets in the gradient definition but it's still relative to the top left corner, and the result would differ if the window size changes.
Here's my current code :
body
{
background: linear-gradient(
150deg,
rgba(180,214,14,0.0) ,
rgba(180,214,14,0.0) 70px,
rgba(180,214,14,0.4) 80px,
rgba(152,197,10,0.5) 150px,
rgba(0,0,0,0.4) 151px,
rgba(0,0,0,0) 160px
), no-repeat 0 0 !important;
background-attachment: fixed !important;
/* background-position: 80% 80% !important; */
background-repeat: no-repeat !important;
}
Any advice is welcomed !
I think you are correct, in that the background-position property only works for images and not gradients. At least that's what I'm finding by playing around with it.
So this isn't an answer to "how to make background-position work for gradients", but rather a suggestion to put your gradient on a different element and position IT to the bottom right.
Like:
div {
position: absolute;
right: 0;
bottom: 0;
width: 160px;
height: 160px;
background: linear-gradient(
150deg,
rgba(180,214,14,0.0) ,
rgba(180,214,14,0.0) 70px,
rgba(180,214,14,0.4) 80px,
rgba(152,197,10,0.5) 150px,
rgba(0,0,0,0.4) 151px,
rgba(0,0,0,0) 160px
), no-repeat 0 0;
background-position: center;
}
Granted, you'll probably have to change the gradient to fit better within that element, but I think this might be the only way to achieve what you're trying to do.
Also, you'll want to make sure that body has position: relative (or whatever the containing element is).
I have to do the following:
The top of the div is an image of a gradient, then in the bottom it continues as a solid color. Can I do this with simple CSS? I know the following is invalid.
{background: url(img/right_column_bg_top.png) no-repeat rgba(10,26,39,1) top 225px;
Note: the first 225px, which the image fills, should be without the background-color
As far as I know, you need to use a gradient for the solid color, so that you can set it correctly.
The CSS would be:
.imgbg {
width:255px;
height:355px;
background: url('http://blue2.hu/danone/nogravity/img/right_column_bg_top.png'), linear-gradient(90deg, #f7d8e8, #f7d8e8);
background-position: 0px 0px, 0px 112px;
background-repeat: no-repeat, no-repeat;
background-size: 255px 112px, 255px 233px;
}
Here is your updated fiddle
Basic suport should be fine for browsers supporting multiple backgrounds, the only problem would be with IE <= 8. Gradient background could be a problem with IE9, but I think that it should work (I can not test IE9). If it would be really a problem, see colozilla for a fix.
Check out this fiddle and tell me if this is what you want.
FIDDLE
HTML
<div class="imgbg"></div>
CSS
.imgbg {
width:255px;
height:355px;
background:#f7d8e8 url('http://placehold.it/255x255') no-repeat;
}
I would do the following:
#myDiv { background: #f7d8e8 url('/img/right_column_bg_top.png') repeat-x ; }
This will just put your background image on the top of the div; the rest of it, will be the color you selected for the entire background of the div.
I've got three background images, all of width 643px. I want them to be set out like so:
top image (12px height) no-repeat
middle image repeat-y
bottom image (12px height) no repeat
I can't seem to do it without getting them to overlap (which is a problem because the images are partially transparent), is something like this possible?
background-image: url(top.png),
url(bottom.png),
url(middle.png);
background-repeat: no-repeat,
no-repeat,
repeat-y;
background-position: left 0 top -12px,
left 0 bottom -12px,
left 0 top 0;
Your problem is that the repeat-y is going to fill the whole height, no matter where you position it initially. Thus, it overlaps your top and bottom.
One solution is to push the repeating background into a pseudo element positioned off of the container by the 12px at the top and bottom. The result can be seen here (the opacity in the demo is just to show that there is no overlap going on). Without opacity, see here. The relevant code (tested in CSS3 browsers: IE9, FF, Chrome):
CSS
div {
position: relative;
z-index: 2;
background: url(top.png) top left no-repeat,
url(bottom.png) bottom left no-repeat;
}
div:before {
content: '';
position: absolute;
z-index: -1; /* push it to the background */
top: 12px; /* position it off the top background */
right: 0;
bottom: 12px; /* position it off the bottom background */
left: 0;
background: url(middle.png) top left repeat-y;
}
If you needed or wanted IE8 support (which does not support multiple backgrounds), then you could put the top background in the main div, and put the bottom background in by using the div:after pseudo element positioned to the bottom of the container.
If you can add padding/borders to the block equal to the backgrounds you want to position without overlapping other block, you can use the background-clip & background-origin to position the top and bottom backgrounds over the paddings/borders, and the repeating background over the content/paddings+content.
Here is an example: http://dabblet.com/gist/2668803
For your code, you'll possibly need to add something like this:
padding: 12px 0;
background-clip: padding-box, padding-box, content-box;
background-origin: padding-box, padding-box, content-box;
or
border: solid transparent;
border-width: 12px 0;
background-clip: border-box, border-box, padding-box;
background-origin: border-box, border-box, padding-box;
And you'll get what you need. If you can't get the paddings/borders, the pseudo-element like ScottS mentioned would work perfectly.
Try do it like this:
background: url(PICTURE.png) left top no-repeat, url(PICTURE2.png) right bottom no-repeat, url(PICTURE3.jpg) left top no-repeat;
}
EDIT:
Was just an example, but here's the css with your css:
background: url(top.png) left 0px top -12px no-repeat, url(middle.png) left 0px top 0px repeat-y, url(bottom.png) left 0px bottom -12px no-repeat;
}
I actually found a simpler fix, because I was having this same issue with a horizontal navigation.
Rather than adding code like the other answers you just have to list it differently in your CSS. The center image that repeats needs to be listed last, not first or second.
In my code it looks like this:
background-image: url(../images/leftNav.gif), url(../images/rightNav.gif), url(../images/centerNav.gif);
background-position: left, right, center;
background-repeat: no-repeat, no-repeat, repeat-x;
to use backgroud-position with 2 arguments, must to Write in extended writing backgroud-position-x and backgroud-position-y
background-position-x: left 0;
background-position-y: top -12px, bottom -12px, top 0;
A radical but effective way to deal with this, if:
you want to apply backgrounds with no overlapping to a ":before"
the ":before" element as a known max height
&:before {
background: url('vertical-line.png') no-repeat 0px,
url('vertical-line-repeat.png') no-repeat 140px,
url('vertical-line-repeat.png') no-repeat 200px,
url('vertical-line-repeat.png') no-repeat 260px,
url('vertical-line-repeat.png') no-repeat 320px,
url('vertical-line-repeat.png') no-repeat 380px,
url('vertical-line-repeat.png') no-repeat 440px,
url('vertical-line-repeat.png') no-repeat 500px,
url('vertical-line-repeat.png') no-repeat 560px,
url('vertical-line-repeat.png') no-repeat 620px,
url('vertical-line-repeat.png') no-repeat 680px,
url('vertical-line-repeat.png') no-repeat 740px;
}
Here's a method that uses 3 div's for each of the Top, Middle, and Bottom images that are transparent to apply to your webpage.
Background wallpaper is optional.
Tested in modern browsers and is IE8 friendly.
This method allows you to treat the body element as it should be treated, i.e., your webpage markup does not need to be in a wrapper or containing element.
jsFiddle Example
jsFiddle Example with centered filled
Since the above example uses image place holder content that is without transparency for Top and Bottom images, you can verify markup works with transparency with this jsFiddle that uses mini transparent icons in repeat mode HERE.
The only (practical, non hair-threatening) way I see is do do that in Javascript, when the page has loaded, and when it is resized, with a canvas sized to fit the innerHeight and the 3 images: draw the first one once at the top, draw the second as many times as required to cover the remainder of the canvas, and draw the 3rd one at the bottom of the canvas. Position the canvas at 0,0 with a ridiculously negative z-index.
I had a go at it with 3 images (643 x 12, 100 and 12) and of course the first issue I saw is that the 3rd image is drawn over part of the last iteration of the 2nd image -- unless you have a window height of exactly 12+12+(p2.height*X), you'll have some overlap. But that's expected, right?
I think z-index will fix this because z-index only affects CHILD elements, meaning you can't mess up anything else on the page that uses z-index.
top and bottom images z-index:3;
middle image z-index:2; background-repeat:repeat-y;