0

Here is a sample snippet:

.tabs {
  display: flex;
  position: relative;
}
.tab {
  height: 100px;
  background: lightgray;
}
.content {
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  display: none;
  background: lightgreen;
}
.open .content {
  display: block;
}
.footer {
  height: 50px;
  background: lightblue;
}
<div class="tabs">
  <div class="tab">
    <div class="header">Tab 1</div>
    <div class="content">Content 1</div>
  </div>
  <div class="tab open">
    <div class="header">Tab 2</div>
    <div class="content">Content 2</div>
  </div>
</div>
<div class="footer">Footer</div>

The height of absolute positioned green content equals to the height of its relative positioned container. So it overlaps the footer. Is it possible to keep top position relative and to set bottom to 0? Something like:

.content {
  position: absolute;
  left: 0;
  width: 100%;
  top: relative; /* Not supported */
  bottom: 0;
  display: none;
  background: lightgreen;
}

I can set top explicitly, say, to 20px. Or I can calculate and set it using JavaScript. Is there a CSS only solution without pre-calculated top value?

Denis
  • 1,167
  • 1
  • 10
  • 30
  • 1
    You want it to respect the page flow but expand to fill the rest of the empty space, you can't do that with absolute positioning, you can do it with flexbox and flex grow – Kareem Kamal Sep 26 '21 at 09:26
  • It seems that I cant use flex here, because left position of both tab contents should be 0. – Denis Sep 26 '21 at 09:29
  • 1
    you'd only have one tab shown at a time right? – Kareem Kamal Sep 26 '21 at 09:31
  • Yes, one tab at a time – Denis Sep 26 '21 at 09:31
  • 1
    and does the structure have to be like this, if you split it into a tabs container and a content container that shows one at a time that seems better, but I'm not sure if it fits with your use case, what you're asking for doesn't exist so you need a bit of restructuring to reach the desired result without fixed values. – Kareem Kamal Sep 26 '21 at 09:41
  • Yes, I can't split headers and contents into separate blocks. I think you are right, that it's impossible to implement. I hoped that there could be some magick with nested `div`s or CSS3 stuff. – Denis Sep 26 '21 at 09:57
  • 1
    @Denis Maybe this can be accomplished with CSS but I think you need to change your HTML structure to be more readable and easier to maintain as well. tabs row doesn't need to be in the same element as their content. I can give you a better HTML structire and CSS if you want. – Amir Meimari Sep 26 '21 at 10:10
  • The HTML structure seems to be natural. A header and a content for each section are at the same place in the HTML document. If I'll split header from content, it will be harder to mantain such a document. For example then a user opens/closes a tab then I have to update two element containers and to guarantee that they are in sync. It seems that the simplest solution is to fix header's height and to set `top` to a fixed pre-calculated height of the header. – Denis Sep 26 '21 at 10:34

2 Answers2

1

Here is an idea using CSS grid to achieve what you want without position:absolute

.tabs {
  display: grid;
  grid-auto-flow:column; /* column flow */
}
.tab {
  display:contents; /* remove the tab div */
}
.header {
  background: lightgray;
}
.content {
  /* make all the content above each other*/
  grid-row:2;
  grid-column:1/span 20; /* use a big value here, at least equal to number of tab*/
  /**/
  height: 100px;
  display: none;
  background: lightgreen;
}
.open .content {
  display: block;
}
.footer {
  height: 50px;
  background: lightblue;
}
<div class="tabs">
  <div class="tab">
    <div class="header">Tab 1</div>
    <div class="content">Content 1</div>
  </div>
  <div class="tab open">
    <div class="header">Tab 2</div>
    <div class="content">Content 2</div>
  </div>
</div>
<div class="footer">Footer</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Cool, it works! It's interesting why `grid-column: 1 / -1;` doesn't work. Maybe because of `display: contents;` – Denis Sep 27 '21 at 09:18
  • 1
    @Denis display:contents play no role here, `1/-1` won't work like you expect because have no *explicit* columns. Related for more detail: https://stackoverflow.com/a/56932610/8620333 – Temani Afif Sep 27 '21 at 20:43
0

You can apply a margin to the footer to separate it from the green content.

.footer{
    margin-top: 20px;
 }
Dev Enock
  • 86
  • 7
  • It works, but I have to pre-calculate this margin. It's much easier to set `.content { top: 20px; }` Is it possible to solve it without pre-calculation? – Denis Sep 26 '21 at 09:36