CSS Question: Two Backgrounds on the Same Element?

code 0 comments suggest edit

As part of my site’s redesign, I wanted to keep the drop shadow effect on the left and right borders of my main content area. No problem I naively thought, I’ll simply add two background elements to the main div. I named the div “background” like so:

<div id="background">
</div>

And in my style sheet, I tried the following:

#background
{
    background: url(leftBorder.gif) repeat-y left;
    background: url(rightBorder.gif) repeat-y right;
}

Unfortunately this did not work as only one of the background images showed up. What I ended up resorting to was using two nested divs. The inner div would contain the main content and the right border while the outer div would display the left border.

<div id="backgroundLeft">
   <div id="background">
   </div>
</div>

At this point, I needed the two divs to overlap each other just right. The inner div needed to align over the outer div’s right edge. On the left side, the inner div needed to expose the outer div’s left edge so that the background image would be displayed. Here’s the CSS I used.

#backgroundleft
{
    margin: 0px;
    background: url(leftBorder.gif) repeat-y left;
    width: 784px;
}

#background
{
    background: url(rightBorder.gif) repeat-y right;
    margin-right: -11px;
    margin-left: 11px;
    position: relative;
    top: 0px;
    left: 0px;
    padding-top: 3px;
    width: 783px;
}

So my question to you CSS gurus out there (if any), is there a better way for me to accomplish this?

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

35 responses

  1. Avatar for Kieran Jacobsen
    Kieran Jacobsen April 4th, 2005

    You can have different classes so to speak of elements, but thats still not going to help as you have tried. My i suggest making the a single image?

  2. Avatar for Scott Elkin
    Scott Elkin April 4th, 2005


    If you make them one image, it wont do what you want. It would stretch the left and right border and make them too thick.



    Funny enough I just had to conquer this same thing yesterday and came up with the same conclusion: nested divs.

  3. Avatar for Scott Elkin
    Scott Elkin April 4th, 2005


    Hey Phil,



    I had to solve this problem again, but with borders on the left and right. Is this too haacky? left.jpg and right.jpg are the respective borders. Set height to whatever it is you need it to be.



    Keep in mind I am a SQL/C#/ASP.NET programmer first. I am just finishing More Eric Meyer, but I am by no means a designer.



    <div style="float:left; background: url(/images/top_left.jpg) top left repeat-y; height: 88px; width:3px;"></div>

    <div style="float:right; background: url(/images/top_right.jpg) top right repeat-y; height: 88px; width:3px;"></div>

    <div style="float:none; background: url(/images/top.jpg) top left repeat-x; height: 88px; width:100%;">

  4. Avatar for Haacked
    Haacked April 4th, 2005

    It's not too "haacky" if it works!

  5. Avatar for Dimitri Glazkov
    Dimitri Glazkov April 4th, 2005

    Phil, you can not avoid using nested elements in this case. However, you don't need to add anything extra to your existing markup. You already have a form element, which hold the div#main element. That's all you need to get this working:



    form

    {

    margin: 0 auto 0 auto;

    width: 799px;

    text-align: left;

    padding: 0px 11px 0px 11px;

    background: url(leftBorder.gif) repeat-y left;

    }



    div#main

    {

    background: url(rightBorder.gif) repeat-y right;

    padding: 10px;

    }

  6. Avatar for haacked
    haacked April 4th, 2005

    Thanks Dimitri, but I over simplified the issue for the sake of clarity. I can't use the form for the left border.

  7. Avatar for Dimitri Glazkov
    Dimitri Glazkov April 4th, 2005

    What stops you from it? Wanna email me?

  8. Avatar for Scott Elkin
    Scott Elkin April 5th, 2005

    Sorry, my last one didnt work quite right in IE. Here is a better one:



    <style>

    #sitemast {background: url(/images/top.jpg) top left repeat-x;}

    #sitemast div {height: 88px;}

    #sitemast .leftborder {

    float: left;

    background: url(/images/top_left.jpg) top left repeat-y;

    width: 3px;

    }

    #sitemast .rightborder {

    float: right;

    background: url(/images/top_right.jpg) top right repeat-y;

    width: 3px;

    }

    #sitemast .content {

    text-align: center;

    }

    </style>

    <div id="sitemast">

    <div class="leftborder"></div>

    <div class="rightborder"></div>

    <div class="content">blah</div>

    </div>

  9. Avatar for Dimitri Glazkov
    Dimitri Glazkov April 5th, 2005

    Guys, whatever markup you do, please, I beg you, don't create empty divs. It's like a sentence with only a period in it. Think structurally, think semantically :)

  10. Avatar for Jonas Verhaert
    Jonas Verhaert July 5th, 2006

    you can put a image in the border...
    its the best way to you set a background image in the left and right border...

  11. Avatar for Henry Felton
    Henry Felton August 18th, 2006

    Having just come across this problem myself I've also had to resort to nested divs, which seems a bit messy and wasteful but there's no real alternative. CSS3 will bring border-image but don't see how would do what you suggest now Jonas?

  12. Avatar for anonymous email
    anonymous email August 30th, 2006

    Oh guys, I tried to do the same thing but ended up with different interpretation in different browsers. Nightmare. Somebody has a cross browser solution?

  13. Avatar for Str187
    Str187 June 25th, 2007

    i like the idea however it looks pretty hard
    can't you use borders for this ?

  14. Avatar for Vi
    Vi July 8th, 2007

    Too bad there is no pure CSS solution. My problem was/is very similar to the one described by Phil. As a part of a CSS-text button design I wanted to have two backgrounds for a link tag. One x-repeated (the width of the element is not known in advance) and one not repeated on either left or right. After several tries I had to resort to an embedded div (floated left) tag within the link for the non repeated image.
    With Firefox it didn't work until I added a nbsp to the previously empty div (to please Dimitri).

  15. Avatar for Gasper Markic
    Gasper Markic September 25th, 2007

    Hi
    I think nesting DIVs is the best way it can be done in CSS1.
    Example bellow is dealing with top and bottom background of a dynamic height cell.
    <div style="height:60px; background: url(top.jpg') no-repeat top;">
    <div style="height:60px;background: url(bott.jpg') no-repeat bottom; padding:4px 0px 4px 0px;">
    CONTENT
    </div>
    </div>

  16. Avatar for CorgaN
    CorgaN December 12th, 2007

    Using an empty div without any content is a mistake. I suggest using background in the outer div and apply another in the inner element:
    <div class='borderLeft'>
    link
    </div>
    You may change tag "a" with any other tag (span, p, etc).

  17. Avatar for Christina
    Christina March 18th, 2008

    To do what you're wanting you don't have to use css, or nested divs or anything... while this won't work in every situation... for the fades on either side of your body it works fine....
    Do a background image like this one:
    http://zencart-demo-store2....
    and set it to repeat-y in the css...
    Hope this helps!

  18. Avatar for John
    John March 20th, 2008

    how would you do this :
    { Background Properties }
    table, tr, td { background-color:transparent;}
    body {
    background-color:none;
    background-image:url('http://ipih.net/images9Y935...
    background-attachment:fixed;
    background-position:top center;
    background-repeat:no-repeat;
    background-image: url(http://ipih.net/images/vid6...
    background-attachment: fixed;
    background-position: bottom right;
    background-repeat: no-repeat;
    background-color: #ffffff;
    cursor: ;
    }
    .FreeCodeSource.com { Table Properties }
    .commonbox {
    border-style:solid;
    border-width:0;
    border-color:000000;
    background-color:transparent;
    background-image:url('Enter Image URL');
    background-repeat:repeat;
    background-attachment:fixed;
    background-position:top center;
    }
    .commonbox h1, .commonbox h2 {background-color:transparent;}
    .commonbox .evenrow {background-color:transparent;}
    { Text Properties }
    .usercontent {font-family:arial !important; }
    .commonbox h1, .commonbox h2 {font-family:arial !important; }
    .data, .controlpanel .q {font-family:arial !important; }
    { Link Properties }
    .usercontent a, .usercontent a:link, .usercontent a:visited, .usercontent a:active {font-style:normal; }
    .usercontent a:hover {font-style:normal; }
    { Button Properties }
    #controlPanelButtons a, #controlPanelButtons a:link, #controlPanelButtons a:visited {background-color:transparent;border-color:transparent;font-family:arial !important; border-style:solid !important; }
    #controlPanelButtons a:hover {background-color:transparent;border-color:transparent;}
    { Misc Properties }
    .commonbox .dr {background-color:transparent;}}
    http://cubancouncil.com/fri...

  19. Avatar for aeron
    aeron July 28th, 2008

    hot to set common box wifth???

  20. Avatar for Fitz
    Fitz September 17th, 2008

    Hey Guys, I don't know if you found a better way to do this, but I have managed to do this without resorting to nested divs or any sort of what I would call hacks. I have my background image as normal and then I add my second image which I want under the text but not repeated like the background image. So I add the second image like:

    <img src="/images/image.png" alt="image.png" class="alignleft">

    The magic happens in the stylesheet for alignleft:

    img.alignleft {
    /*padding: 4px;
    margin: 0 7px 2px 0;
    display: inline;*/
    position:absolute;
    left:0px;
    top:0px;
    z-index:-1;
    }

    The key here is the z-index item. I have set it to negative 1 (-1) because this puts it behind everything but the background. Hope this isn't too late and that it helps someone else out.

  21. Avatar for CCH
    CCH October 5th, 2008

    One thing you could try would be using tables instead of divs, for example:
    [code]
    <table><tr><td style="background:url('bgleft.jpg') repeat-y;"> </td><td>{main content here}</td><td style="background:url('bgright.jpg') repeat-y;"> :</td></tr></table>
    [/code]
    This will produce a box with the borders on each side. You may need to set a fixed width tag in the border cells so they don't stretch weird, and format the table with no padding, borders, or spacing, but otherwise, you can use this to make the effect you want. If you plan to do a few like this, just move the style info into the header and use a class tag instead.
    This may require a small amount of extra coding, but is cleaner than nested divs and compatible in all browsers that support tables. And unlike DIVs, they don't create a linebreak, so you can put them next to each other or on top of each other. You can even put them inside another table if you're trying to make a sidebar.
    Last thing you can do is use php coding to draw an image based button. Basically there's codes that allow you to generate a php based image, it can be dynamically drawn based on the text you enter and because it's generated on the server, it will look the same on all browsers. The resulting code in your page will be a IMG instead of a DIV, something like this:
    [code]
    <img src="button.php?text={button text here}">
    [/code]
    Then in your php file enter the following code:
    [code]
    header('Content-type: image/png');
    function getColor( $color , $image )
    {
    $red = 100;
    $green = 100;
    $blue = 100;
    $ret = array();
    if( preg_match("/[#]?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i",$color,$ret) )
    {
    $red = hexdec($ret[1]);
    $green = hexdec($ret[2]);
    $blue = hexdec($ret[3]);
    }
    return imagecolorallocate($image,$red,$green,$blue);
    }
    function writeText( $image , $size , $xpos , $ypos , $color , $font , $text , $shadow )
    {
    $color = getColor($color,$image);
    // Create a drop shadow
    if( $shadow != '' )
    {
    $shadow = getColor($shadow,$image);
    imagettftext($image,$size,0,$xpos+1,$ypos+1,$shadow,$font,$text);
    }
    // Write the text
    imagettftext($image,$size,0,$xpos,$ypos,$color,$font,$text);
    }
    $left = @imagecreatefrompng( 'leftborder.png' );
    $right = @imagecreatefrompng( 'rightborder.png' );
    $text = $_GET["text"];
    $checksize = imagettfbbox(10,0,'timesbd.ttf',$text); //10=font size
    $w = abs($box[0]) + abs($box[2]);
    $imgwidth = $w + 10; //10=size of both borders and spacing between borders and text
    // Create a new image
    $full = imagecreatetruecolor( $imgwidth, 64 ); //64=button height, no word wrap
    // Turn off alpha so we can get a clean boder to set to transparent
    imagealphablending( $full, false );
    // Set the trans color
    $col = getColor('22ff22',$full);
    imagefilledrectangle( $full, 0, 0, 256, 64, $col );
    imagecopy($full,$left,0,0,0,0,5,64); //5 is width of left border, make sure source border image is at least as tall as the height of the button, it won't tile
    imagecopy($full,$right,0,0,0,0,$imgwidth-5,64); //-5 is to right align the right border, change 5 to whatever the width of the right border is
    imagealphablending( $full, true );
    writeText($full,10, round(($imgwidth)/2), 51,'ffffff','timesbd.ttf',$text,'000000');
    //writeText($full,{font size, must match previous list}, round(($imgwidth)/2), 51,{font color in HEX},'timesbd.ttf',$text,{font shadow in HEX, leave empty for no shadow});
    //start output of image
    imagealphablending($full, false);
    imagesavealpha($full, true);
    imagepng($full);
    imagedestroy($full);
    return;
    [/code]
    This will take your input text and create a button with a transparent background and borders on left and right sides. You can replace $imgwidth with a fixed width if you want, but make sure it's enough to fit all your text. You will also need to upload the ttf font file of the font you want your images to appear in (means you can make it any font you want)

  22. Avatar for The wwwoodman
    The wwwoodman October 28th, 2008

    Is your width fixed? If so, use a single image 1 pixel high of your fixed width with gradients on either side that will repeat vertically. Put this in your outside div and nest your content div on top of it. If your content div has a color background then Bob's ur uncle! Cleaner Simpler.

  23. Avatar for Gremlette
    Gremlette November 9th, 2008

    This seems the ONLY relevant thing on the web when I was trying to sort out a similar issue.
    What I have is a Pure CSS XHTML tableless layout.
    The main body is Centred.
    What I wanted was a different repeating background to the right and different to the left.
    Essentially just a different block colour / image was made to cover up part of the background on one side.
    I ended up positioning the image on the left to expand over the left background. All browsers turn out to NOT give horizontal bars appearing IF the overflow goes left - including IE7. This also allows you to be CSS 2.1 compliant without trying to use CSS3 only overflow-x:hidden and trying to futile hack it for IE.

  24. Avatar for Milo
    Milo January 7th, 2009

    I'm not sure if this is a good solution. But what I did with one of my websites is I created a 1px height image where the shadow was on the left and right part and the middle was just white. And I just applied the image as background and repeated it. To see what I mean save the shadow on that website www.forestview.com.ph

  25. Avatar for How do I change the height?
    How do I change the height? January 26th, 2009

    How do I change the height?
    Adding height: 2000px; does not work.

  26. Avatar for DePalmo
    DePalmo July 16th, 2010

    Hello.
    I had the same problem and I did it like this:
    [code]
    <div id="container">
    <div id="container-left-border">&nbsp;</div>
    <div id="container-right-border">&nbsp;</div>
    </div>

    #container {
    position: relative; /* required for this to work */
    padding: 0px 30px 0px 30px; /* dinamically resizing of div element */
    background-color: #000000; /* in my case, it needed to be black - change to whatever you need*/
    }
    #container-left-border {
    background: url(../images/background.gif) top left repeat-y;
    position: absolute; /* required for this to work */
    left: 0; /* it needs to be positioned left */
    top: 0;
    bottom: 0;
    /* last three options means that the div element will be the same height as the container */
    width: 20px; /* width of border - change to whatever you need */
    }
    #container-right-border {
    background: url(../images/background.gif) top right repeat-y;
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 20px;
    }
    [/code]
    I think that this is the simplest way, but I sure that out there you could find something simpler. I'm not a real designer :)

  27. Avatar for DePalmo
    DePalmo July 16th, 2010

    Sorry, I copied too quickly and some errors are showing. My bad :)
    Everything in html code is the same, updated css is:
    body {
    padding: 0px 50px 50px 50px; /* this helps div to be dynamical in width */
    }
    #container {
    position: relative;
    padding: 0px 30px 0px 30px; /* spacing for the borders... so the content will NOT overlap */
    background-color: #000000;
    }
    Everything else is the same.

  28. Avatar for Luggruff
    Luggruff September 24th, 2010

    Hey, a bit late perhaps.. but I can without a doubt say I've got the most simple solution:
    .yourdoublebgimage{
    background-image: url('twobgright.png'), url('twobgleft.png');
    background-repeat: repeat-y, repeat-y;
    background-position: left, right;
    }
    ..you simply seperate the images by a comma, and on the second and third attributes (repeat and position), you seperate by comma accordingly to wich background image you've written first. A third, centered image, does work, though if repeated, it will cover the one on the right (didn't find a solution to this.. then you may just have to nest it)

  29. Avatar for Ro
    Ro September 26th, 2010

    Thanks for posting this!
    This is exaclty what I needed. I can't believe I didn't find this information earlier.

  30. Avatar for Mike
    Mike October 1st, 2010

    Why not just put both images back in the background declaration, just as you can define multiple element declarations in CSS with a comma, you can do the same with the images and params.
    .example_with_two_images
    {
    background-image: url(leftBorder.gif), url(rightBorder.gif);
    background-repeat: repeat-y;
    background-position: left, right;
    }

  31. Avatar for Atif
    Atif December 22nd, 2010

    hey mike and Luggruff,
    beautiful technique guys. I didnt know we could use two by adding commas until today. You guys are life saver. cheers

  32. Avatar for Shannon
    Shannon January 19th, 2011

    I'm trying to do something along the same lines. This is the closest thread I've found.
    I want to use different background images for my content h2
    here is the site: http://enamoured.eightcrazydesigns.com/
    What I'd REALLY like to do is to have 4 different images that would be used. The first excerpt with image 1, second excerpt with image 2, third with image 3, fourth with image 4, fifth with image 1, etc.
    However I've also considered just using two images and designating them based on odd and even post numbers.
    Any clue how to do this?

  33. Avatar for Profesor
    Profesor February 5th, 2011

    First of all a BIG THANK YOU to Lugroff and Mike. That´s what I did exactly for my shadow to work on BOTH the left side and the right side of my page.
    div.mainmiddle-wrapper-m {
    padding: 0px 15px 0px 15px;
    /* border-left: 1px solid #D2D2D2; */ this was how the template was originally set up
    /* border-right: 1px solid #D2D2D2;*/ this was how the template was originally set up
    background: #ffffff;
    background-image: url(../images/main_l.png), url(../images/main_r.png);
    background-repeat: repeat-y;
    background-position: left, right;
    So basically i just added the two shadow images, 10pixelX10pixel png shadow, separated by the comma. I also had to do some slight modifications on the shadow of the top left and bottom left (wrapper-m tl and wrapper-m bl) because the lines weren´t alligned exactly. Now the main middle wrapper has a lot more DEPTH to it thanks to the shadows.
    Here are the final results and it definnetely makes the page "POP OUT" and much more visually attractive.
    www.profesorpirata.com
    Thanks again for your help and also for the Great Site!!
    Cheers,

  34. Avatar for Nidhi Mangal
    Nidhi Mangal April 11th, 2011

    Hi Mike/Professor,
    Thanks for posting your comments. I have got the same issue. I want to put tow backgounds for a link in the navigation Home. I tried background-image: url(nav_leftBorder.gif), url(nav_rightBorder.gif); using comma to seperate two images. However, It doesn't work for me in any of the browsers.
    My ccs as follow:
    #topnav ul li a:hover{
    background-image: url(../images/btn_nav_left.png), url(../images/btn_nav_right.png);
    background-repeat: no-repeat;
    background-position: left, right;
    background-color: #02441d;}
    Please suggest.
    Nidhi

  35. Avatar for Laksh
    Laksh February 15th, 2013

     Thanks , really helpful.