wutax
wutax

Reputation: 43

CSS - Avoid removing text flow on absolute positioning

I'm trying to create a tabulator system with CSS only. So far it works fine, but the absolute positioning of the content boxes won't allow me to add more divs at the bottom. Is there any way to fix this problem? I know that absolute positioned objects will not normally influence the text flow, but can you still make it happen?

HTML File:

<!DOCTYPE html>
<html>
    <head>
        <title>CSS Tabs</title>
        <link rel="stylesheet" type="text/css" href="menutabs.css" />
        </style>
    </head>
    <body>
        <div class="main">
            <ul class="tabs">
                <li>
                      <input type="radio" checked name="tabs" id="tab1">
                      <label for="tab1">One</label>
                      <div id="tab-content1" class="tab-content animated fadeIn">
                        "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                      </div>
                </li>
                <li>
                      <input type="radio" name="tabs" id="tab2">
                      <label for="tab2">Two</label>
                      <div id="tab-content2" class="tab-content animated fadeIn">
                      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                      </div>
                </li>
                <li>
                      <input type="radio" name="tabs" id="tab3">
                      <label for="tab3">Three</label>
                      <div id="tab-content3" class="tab-content animated fadeIn">
                      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                      </div>
                </li>
            </ul>
            <div>
                <p class="sample">Sample Text</p>
            </div>
        </div>
    </body>
</html>

CSS File:

.main {
    width: 80%;
    margin: 0px auto;
}

.tabs input[type=radio] {
    position: absolute;
    visibility: hidden;
}
.tabs {
    list-style: none;
    position: relative;
    padding: 0;
}
.tabs li{
    float: left;
}
.tabs label {
    display: block;
    padding: 10px 20px;
    color: #585;
    font-size: 24px;
    background: rgba(255,255,255,0.2);
}
.tabs label:hover {
    background: rgba(60,90,60,0.2);
}

[id^=tab]:checked + label {
    background: #585;
    color: white;
}

[id^=tab]:checked ~ [id^=tab-content] {
    display: block;
}
.tab-content{
  display: none;
  background: #585;
  padding: 5px;
  color: white;
  position: absolute;
  left: 0;
}

.sample {
    background-color: #585;
    color: white;
    text-align: center;
}

Upvotes: 4

Views: 375

Answers (2)

Josh Crozier
Josh Crozier

Reputation: 241078

If you know the height of the containing elements you could obviously just set a height on the parent element and avoid the collapsing issues with the absolutely positioned elements. This isn't really ideal though, as it should work with dynamic content.

Using the current coding, this could be solved with a little JavaScript, however if you want to avoid JS, the solution would be to remove the absolute positioning and change the markup.

See it for yourself - Working example

I removed the input/label elements from the li tabs and moved them to the root of the .main element. Instead of floating the li elements, they are now inline-block elements to avoid collapsing issues. Additionally, I wasn't able to use generalized attribute selectors, such as [id^=tab-content], instead I had to change them to specific id selectors. This is a little more redundant, but it is unfortunately required in this instance due to the markup change. This works because there are no longer any absolutely positioned elements.

Updated HTML

<div class="main">
   <input type="radio" name="tabs" id="tab1" checked>
   <label for="tab1">One</label>
   <input type="radio" name="tabs" id="tab2">
   <label for="tab2">Two</label>
   <input type="radio" name="tabs" id="tab3">
   <label for="tab3">Three</label>
   <ul class="tabs">
      <li>
         <div id="tab-content1" class="tab-content animated fadeIn">TAB1</div>
      </li>
      <li>
         <div id="tab-content2" class="tab-content animated fadeIn">TAB2</div>
      </li>
      <li>
         <div id="tab-content3" class="tab-content animated fadeIn">TAB3</div>
      </li>
   </ul>
   <div>
      <p class="sample">Sample Text</p>
   </div>
</div>

Updated CSS

.main {
    width: 80%;
    margin: 0px auto;
}
.tabs {
    list-style: none;
    position: relative;
    padding: 0;
}
.tabs li {
    display:inline-block;
}
[id^=tab]:checked + label {
    background: #585;
    color: white;
}
#tab1:checked ~ .tabs li #tab-content1 {
    display: block;
}
#tab2:checked ~ .tabs li #tab-content2 {
    display: block;
}
#tab3:checked ~ .tabs li #tab-content3 {
    display: block;
}
.tab-content {
    display: none;
    background: #585;
    padding: 5px;
    color: white;
}
.sample {
    background-color: #585;
    color: white;
    text-align: center;
}
label {
    padding: 10px 20px;
    color: #585;
    font-size: 24px;
    background: rgba(255, 255, 255, 0.2);
    float:left;
    position:relative;
    z-index:1;
}
label:hover {
    background: rgba(60, 90, 60, 0.2);
    cursor:pointer;
}
input[type=radio] {
    display:none;
}

Upvotes: 1

Danield
Danield

Reputation: 125551

There are 2 issues here.

FIDDLE

First of all the list items in your ul are floated left. This means that the list has no height.

The fix: add a cleafix to the ul.

<ul class="tabs clearfix">

.clearfix:after {
    content:"";
    display:table;
    clear:both;
}

Second: To overcome the absolutely positioned content - just add a margin-top to the div that follow.

Of course - this will only work if you know in advance the height of your content (Thanks @JoshC)

If you don't know the height - then I think you'll just have to redesign your markup. A quick fix would be to add the extra divs to the content itself.

.sample {
    background-color: #585;
    color: white;
    text-align: center;
    margin-top: 90px; /* height of content */
}

Upvotes: 1

Related Questions