Imagine a scenario where you have a modal with tabs and tab content. Each tab has a different height - the first tab is 100px high, the second tab is 500px high, and the third tab is 50px high. The challenge here is to ensure that the modal body always matches the height of the tallest tab (500px), so when switching between tabs, the modal remains consistent in size.
There are certain limitations in achieving this:
- You cannot set the tab content area wrapper to position: relative and each tab to position: absolute; top: 0; left: 0; because absolute-positioned elements do not occupy space in the layout.
- Hiding all tabs except the active one will cause the tabs to stack vertically, resulting in extra space above each tab. This leads to the overall height of the modal's body being the sum of the heights of all tabs combined.
To better understand the issue, please refer to the example linked below. Toggle between "End Goal" and "Actual" to visualize the desired outcome versus the current situation.
I would prefer to avoid using JavaScript to dynamically adjust the height of each tab since it would involve constantly checking for changes due to user interactions. This approach may introduce complexities and inefficiencies. I am open to exploring alternative solutions if any exist.
As a temporary fix, I might choose a "good" height for the tab container and allow taller tabs to scroll within their designated space if necessary.
Example: https://codepen.io/joshm123/pen/NWrEVjJ (copied below)
HTML
<div class="modal">
<div class="header">
<h2>Welcome!</h2>
</div>
<div class="body">
<div class="tabs">
<button class="tab" onClick="selectTab(1)">Tab 1</button>
<button class="tab" onClick="selectTab(2)">Tab 2</button>
<button class="tab" onClick="selectTab(3)">Tab 3</button>
</div>
<div class="tabs-wrapper">
<div id="tab1" class="tab-content active">
blah blah blah<br/>
blah blah blah
</div>
<div id="tab2" class="tab-content">
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah<br/>
blah blah blah
</div>
<div id="tab3" class="tab-content">
blah blah blah
</div>
</div>
</div>
<div class="footer">
<button id="showEndGoalButton" onClick="toggleView()">Show End Goal</button>
<button id="showActualButton" onClick="toggleView()">Show Actual</button>
</div>
</div>
CSS
.modal {
position: absolute;
width: 500px;
left: calc(50% - 250px);
top: 30px;
border: 1px solid #999;
}
.header {
padding: 10px;
border-bottom: 1px solid #999;
}
.header h2 {
margin: 0;
padding: 0;
}
.body {
padding: 10px;
}
.tabs > .tab {
margin-right; 10px;
}
.tabs-wrapper {
margin: 10px 0;
border: 1px dotted red;
}
.tab-content {
visibility: hidden;
border: 1px dotted blue;
}
.tab-content.active {
visibility: visible;
}
.footer {
padding: 10px;
border-top: 1px solid #999;
text-align: right;
}
/* supporting CSS
- height of tallest tab is 182px
- make all tabs this hard-coded height
- this is not a real solution, but an example
what the end result should be (visually)
*/
.modal #showActualButton {
display: none;
}
.modal.end-goal #showEndGoalButton {
display: none;
}
.modal.end-goal #showActualButton {
display: inline-block;
}
.modal.end-goal .tabs-wrapper {
position: relative;
height: 182px;
}
.modal.end-goal .tab-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
JavaScript
window.selectTab = function (num) {
const tabs = document.querySelectorAll('.tab-content');
const tab = document.querySelector(`#tab${num}`);
tabs.forEach(o => o.classList.remove('active'));
tab.classList.add('active');
}
window.toggleView = function() {
document
.querySelector('.modal')
.classList
.toggle('end-goal');
}