Overlay Divs Without Absolute Position

HtmlCssCss Position

Html Problem Overview


What follows is a long explanation, but it's the only way to effectively communicate the issue I'm trying to resolve...

I am (somewhat desperately, and entirely unsuccessfully) trying to overlay divs without the use of absolute positioning. The need stems from a paypal cart that I place on the site via a Javascript. The cart's natural position is hard against the top margin of the webpage (not its containing div, which is #wpPayPal, or the wrapper for this div, #main).

The script's author strongly recommends against customizing the cart's stylesheet, but I found a tutorial he wrote that enables insertion of the cart into a placeholder div, with positioning instructions for the container that works - I was able to position the cart below the site's top banner section. However...

The cart's HTML form and a ul element within each have height requirements in the cart's stylesheet, and this pushes the page's main content, wrapped by the container div #imageWrapper, too far down the page to be acceptable.

I tried to position #imageWrapper over #main with several ideas gathered from posts on this site with no success. I've tried absolute positioning on #imageWrapper, but this frees the footer to float beneath. #imageWrapper's height is variable, hence I do not want to hold the footer in place with height, since the min-height to prevent overlap would push the footer down too far for much of the site's content.

I also tried pulling position:relative from the cart form's CSS, but the cart immediately floats back to the top of the webpage. Margin, top-margin, etc.,do not remedy this.

I then read an article on using position:relative and z-index to overlay divs. Tried this, too, first by putting z-index: -1 on #main (the div that wraps the paypal cart), but the cart disappears. Not sure where it goes, either, since the site's breadcrumb nav, also wrapped by #main, stayed put.

I then set the z-index for main to 0 and applied position:relative to #imageWrapper with z-index:100. The cart reappeared but still holds #imageWrapper down.

Suggestions are greatly welcomed. I'm not an interface person by any stretch of the imagination, just a guy who knows how to use Google, so thanks in advance for clearly articulating your resolution :) Also, FYI, presently I have the min-height requirement for the cart form set to 0, and set the UL element within to height:auto. With only a single item in the cart, this allows #imageWrapper to move up the page enough to be acceptable, but this is not a viable long-term solution.

Here's an example page - to see the cart, add an item using the dropdown that appears below the main image. In its expanded state, you'll see how #imageWrapper sits against it.

I've included portions of the offending HTML / CSS below:

<div id="main">
    <div id="wpPayPal">
    </div><!--end wpPayPal-->
    <div id="breadcrumbs">
        <span class="B_crumbBox"><span class="B_firstCrumb"><a class="B_homeCrumb" href="/">home</a></span> &raquo;</span></span>
    </div> <!--end breadcrumbs -->
</div><!-- end Main -->

<div id="imageWrapper">
    <div id="imageInnerWrapper">
        <div id="featureImage">
            <div class="filename"><h1>~&nbsp;Bryce Canyon Sunrise | Bryce Canyon | Utah&nbsp;~</h1>
            </div><!--end filename-->

etc...

#main {
    display: inline;
    position: relative;
    z-index: 0;
}

#imageWrapper {
    clear: both;
    width: 840px;
    margin: 0 auto;
    padding: 0;
    position: relative;
    z-index: 100;
}

#imageInnerWrapper {
    width: 840px;
    margin: 0 auto;
    padding: 0;
    position: relative;
    z-index: 100;
}

#featureImage {
    width: 840px;
    margin: 0 auto;
    padding: 0;  
}

#wpPayPal {
    overflow: hidden;
    float: right;
    margin-right: 100px;
    min-width: 365px;
    min-height: 20px;
}

/* Override the default Mini Cart styles */

#wpBody #PPMiniCart form {
    position: relative;
    right: auto;
    width: auto;
    min-height: 0;
}

#wpBody #PPMiniCart form ul {
    height: auto;
}

Html Solutions


Solution 1 - Html

You can now to do this with grid also.

.parent {
  display: grid;
  grid-template-columns: 1fr;
}

.parent div {
 padding: 50px;
 background-color: rgba(0,0,0,0.5);
 grid-row-start: 1;
 grid-column-start: 1;
}

<div class="parent">
  <div class="child1">
  1
  </div>
  <div class="child2">
  2
  </div>
</div>

Solution 2 - Html

Div background for a block with a dynamic height can be implemented using flexbox without an absolute positioning:

/* Every rule not marked by "required" is optional and used only to decorate the example / .block { margin: 10px 50px; display: flex; / required / flex-flow: row nowrap; / required / } .block .background, .block .foreground { box-sizing: border-box; / required / width: 100%; / required / flex: none; / required / } .block .background { background: #9ff; color: #fff; padding: 15px; font-size: 30px; } .block .foreground { padding: 15px; border: solid 1px; margin-left: -100%; / required */ } .block .foreground .outside { position: absolute; top: 5px; left: 8px; }

<div class="block">
    <div class="background">
        Background
    </div>
    <div class="foreground">
        <div>
            <div class="outside">Outside</div> <!-- The "outside" div is also optional -->
            <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Odio incidunt perspiciatis sapiente aspernatur repellat delectus atque quae optio nam? Pariatur explicabo laboriosam dolores temporibus molestiae error ipsa sunt molestias doloremque odio nemo iure similique quae exercitationem, adipisci, ullam dicta esse numquam beatae qui velit asperiores. Dolore, quo illum necessitatibus tempora earum nihil cumque corporis aut error eius voluptatibus quia, pariatur.</div>
        </div>
    </div>
</div>

The solution is supported by about 99% of browsers.

Solution 3 - Html

Simple fiddle: Just CSS

Some guy posted another but it had a bunch of extra unnecessary code and some JS Another post had the answer but was missing something

.over {
  background: rgba(230, 6, 6, .5);
  float: right;
  height: 460px;
  margin-top: -500px;
  margin-right: 159px;
  overflow: visible;
  position: relative;
  width: 560px;
  color: #FFFFFF;
  /* Just for looks*/
  z-index: 1000;
  padding: 20px/* Just for looks*/
}

.over span {
  position: relative;
  /* Just for looks*/
  top: 15px;
  /* Just for looks*/
}

.this {
  width: 560px;
  height: 460px;
  color: #FFFFFF;
  /* Just for looks*/
  padding: 20px;
  /* Just for looks*/
  background-image: url("http://www.tshirtvortex.net/wp-content/uploads/dramaticchipmunk.jpg");
  /* Just for looks*/
}

<div class="this">To BE UNDER</div>
<div class="over"><span>..or not To BE UNDER</span></div>

http://jsfiddle.net/3WDf7/

Solution 4 - Html

>>>>Got it!!! :D

Pure Css solution Very Easy. Put the following.

#main {
float: right;
overflow: visible;
position: relative;
z-index: 1000;
height: 177px;
width: 100%;
}

Replace whatever you have in css #main with what i have done above.

So remove the following:

display: inline;
position: relative;
z-index: 0;

Explanation: Main idea here is to float the main element, make it of certain height so at no point it pushes everything down. But make overflow of it visible. Overflow of content doesn't affect siblings of main element.

Solution 5 - Html

None of the previous answers actually help with your requirement, which is to allow PPMiniCart to expand and contract without pushing imageWrapper down.

The trick here is to give wpPayPal a fixed height large enough to hold the contracted version of PPMiniCart (40px will do - this will give the shopping cart enough room, without pushing imageWrapper too far down).

#wpPayPal {
    height:40px;
}

Then give main (the container that holds wpPayPal) a z-index greater than that of imageWrapper so that it overflows over it.

#main {
    z-index: 1;
}
#imageWrapper {
    z-index: 0;
}

Setting imageWrapper z-index to 100 kind of overdoes it, I would recommend 0 like I did above.

You also need some JavasScript to set overflow: visible on wpPayPal after PPMiniCart expands and remove it before it contracts. Fortunately Mini Cart JS exposes a nice event-driven API that allows custom callbacks. Since you are using jQuery in your webpage let's take advantage of that:

PAYPAL.apps.MiniCart.render({
    parent: 'wpPayPal',
    events: {
        afterShow: function () {
            $("#wpPayPal").css("overflow", "visible");
        },
        onHide: function () {
            $("#wpPayPal").css("overflow", "");
        }
    }
});

Please note the careful choice of afterShow and onHide callbacks, if you try to do it any different (setting overflow: visible before PPMiniCart expands or removing it before PPMiniCart contracts) PPMiniCart will "float up" during the transition.


Finally, a working fiddle is worth a thousand words.

Solution 6 - Html

Figured out an elegant solution for your problem without absolute positioning OR floats using flexbox — main advantage is that both div heights are respected when calculating parent height. Very useful for overlaying text on an image:

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

.container {
  max-width: 500px;
  /*border: 1px solid lime;*/
}

.card {
  display: flex;
  /*border: 1px solid red;*/
  overflow: hidden;
}

.box {
  position: relative;
  min-width: 100%;
  width: 100%;
  flex-basis: 100%;
  flex-grow: 1;
}

.box--image {
  z-index: 1;
  overflow: hidden;
}

.box--image.box--heightrestricted {
  max-height: 300px;
}

.box--text {
  z-index: 2;
  margin-left: -100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: red;
}

.box--text h3 {
  margin: 0;
  padding: 1rem;
}

<div class="container">

  <button onclick="document.getElementById('imagebox').classList.toggle('box--heightrestricted')">toggle image max-height</button>
  <br>
  <br>

  <div class="card">

    <div id="imagebox" class="box box--image box--heightrestricted">
      <img src="https://placeimg.com/640/640/4" alt="" />
    </div>

    <div class="box box--text">
      <h3>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris in urna porta, maximus velit vitae, suscipit eros. Praesent eleifend est at nisi laoreet auctor. Nunc molestie fringilla magna et dictum. Nam ac massa nec erat consequat lacinia in in leo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas sollicitudin nibh nisl, sed molestie lorem lobortis in. Nulla eget purus a risus scelerisque cursus. Praesent nisl dolor, varius eget faucibus sit amet, rutrum non lorem. Ut elementum sapien sed facilisis tempus. Morbi nec ipsum sed lacus vulputate sodales quis ut velit. Quisque id ante quis leo pharetra efficitur nec at mauris. Praesent dignissim hendrerit posuere. Vestibulum venenatis urna faucibus facilisis sodales. Suspendisse potenti. Proin a magna elit. Aenean vitae aliquam est, quis fringilla lectus.</h3>
    </div>

  </div>

</div>

Solution 7 - Html

Also can use flexbox to make a tabs container without absolute position:

/* Flex Overflow */
section {
  display: flex;
  width: 100%;
  overflow: hidden;
}

section article {
  flex: 100% 0 0;
  order: 0;
}

section article:target {
  order: -1;
}

/* UI */
section { background-color: #ecf0f1; }
section article { 
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ecf0f1;
  font-size: 20px;
  min-height: 8em;
  visibility: hidden;
  opacity: 0;
  transition: visibility .5s ease, opacity .5s ease;
}
section article:first-child,
section article:target {
  visibility: visible;
  opacity: 1;
}
section article#zoneA { background-color: #2980b9; }
section article#zoneB { background-color: #16a085; }
section article#zoneC { background-color: #f39c12; }
section article#zoneD { background-color: #8e44ad; }

<ul>
  <li><a href="#zoneA">Zone A</a></li>
  <li><a href="#zoneB">Zone B</a></li>
  <li><a href="#zoneC">Zone C</a></li>
  <li><a href="#zoneD">Zone D</a></li>
</ul>

<section>
  <article id="zoneA">A</article>
  <article id="zoneB">B</article>
  <article id="zoneC">C</article>
  <article id="zoneD">D</article>
</section>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjiversView Question on Stackoverflow
Solution 1 - HtmlpatelarpanView Answer on Stackoverflow
Solution 2 - HtmlFinesseView Answer on Stackoverflow
Solution 3 - HtmlKay Valle GanevView Answer on Stackoverflow
Solution 4 - HtmlMuhammad UmerView Answer on Stackoverflow
Solution 5 - HtmlAnthony AcciolyView Answer on Stackoverflow
Solution 6 - HtmlL Daniel SwakmanView Answer on Stackoverflow
Solution 7 - HtmlNSDView Answer on Stackoverflow