Home > Software design >  Overflow defeats negative margin to hide border
Overflow defeats negative margin to hide border

Time:03-01

I am designing a simple tab bar with a content panel.

To hide the bottom border for the current active tab, I use a negative margin-bottom and a border-bottom to hide the border for that tab.

test1

* {
  box-sizing: border-box;
}

#container {
  width: 500px;
  height: 200px;
  border: 1px solid black;
  background-color: lightgray;
}

#wrapper {

}

ul {
  display: flex;
  margin: 0;
  padding: 2px 2px 0 2px;
  border-bottom: 1px solid black;
}

li {
  padding: 10px;
  margin: 0 2px -1px 0;
  list-style: none;
  border-top: 1px solid black;
  border-left: 1px solid black;
  border-right: 1px solid black;
  border-bottom: 0;
}

li.active {
  border-bottom: 2px solid lightgray;
}

#content {
  padding: 10px;
}
<div id="container">

<div id="wrapper">
<ul>
  <li >Tab 1 (active)</li>
  <li>Tab 2</li>
  <li>Tab 3</li>
</ul>
<div>
<div id="content">
  My content
</div>
</div>

It works perfect.


The problem comes when I want to add more tabs, so it overflows the container. The solution that comes to my mind is using overflow-x: auto;. The problem is that this also adds a vertical scrollbar, and I am not sure why. I could overcome this by using overflow-y: hidden;. But the real problem is that it makes impossible to "delete" the black bottom border of the current active tab anymore.

test2

You can run the snipped below, also you can uncomment the commented html li elements.

* {
  box-sizing: border-box;
}

#container {
  width: 500px;
  height: 200px;
  border: 1px solid black;
  background-color: lightgray;
}

#wrapper {

}

ul {
  display: flex;
  margin: 0;
  padding: 2px 2px 0 2px;
  border-bottom: 1px solid black;
  overflow-x: auto;
}

li {
  padding: 10px;
  margin: 0 2px -1px 0;
  list-style: none;
  border-top: 1px solid black;
  border-left: 1px solid black;
  border-right: 1px solid black;
  border-bottom: 0;
  white-space: nowrap;
}

li.active {
  border-bottom: 2px solid lightgray;
}

#content {
  padding: 10px;
}
<div id="container">

<div id="wrapper">
<ul>
  <li >Tab 1 (active)</li>
  <li>Tab 2</li>
  <li>Tab 3</li>
  <li>Tab 4</li>
  <li>Tab 5</li>
  <li>Tab 6</li>
  <li>Tab 7</li>
  <!--<li>Tab 8</li>
  <li>Tab 9</li>
  <li>Tab 10</li>-->
</ul>
<div>
<div id="content">
  My content
</div>
</div>

test2bis

Does anyone has a solution? If not, what would be an alternate way to accomplish this?

What I really want is to keep hiding the bottom border of the active tab, and also have the possibility of showing an horizontal scroll bar when there is horizontal overflow.

Thank you.

CodePudding user response:

"delete" the black bottom border of the current active tab

You can use border-bottom-color: transparent.

* {
  box-sizing: border-box;
}

#container {
  width: 500px;
  height: 200px;
  border: 1px solid black;
  background-color: lightgray;
}

#wrapper {

}

ul {
  display: flex;
  margin: 0;
  padding: 2px 2px 0 2px;
}

li {
  padding: 10px;
  margin: 0 2px 0 0;
  list-style: none;
  border: 1px solid black;
  
}

li.active {
  border-bottom-color: transparent;
}

#content {
  padding: 10px;
}
<div id="container">

<div id="wrapper">
<ul>
  <li >Tab 1 (active)</li>
  <li>Tab 2</li>
  <li>Tab 3</li>
</ul>
<div>
<div id="content">
  My content
</div>
</div>

showing an horizontal scroll bar when there is horizontal overflow

I think you forgot to close one of your divs, and your content was inside .wrapper! So just fix that up, and stick on overflow: auto and a max width to make sure it doesn't expand.

* {
  box-sizing: border-box;
}

#container {
  width: 500px;
  height: 200px;
  border: 1px solid black;
  background-color: lightgray;
}

#wrapper {
  overflow-x: auto;
  max-width: 100%;
}

ul {
  display: flex;
  margin: 0;
  padding: 2px 2px 0 2px;
}

li {
  padding: 10px;
  margin: 0 2px 0 0;
  list-style: none;
  border: 1px solid black;
  
}

li.active {
  border-bottom-color: transparent;
}

#content {
  padding: 10px;
}
<div id="container">

<div id="wrapper">
<ul>
  <li >Tab 1 (active)</li>
  <li>Tab 2</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
  <li>Tab 3</li>
</ul>
</div>
<div id="content">
  My content
</div>
</div>

CodePudding user response:

To hide the bottom border for the current active tab, I use a negative margin-bottom and a border-bottom to hide the border for that tab.

Instead, you can use box-shadow: 0 -1px black inset; for <ul> and box-shadow: 1px -1px lightgray inset; for li.active.

Once you have done all of this, you don't need negative margin-bottom anymore.

The problem is that this also adds a vertical scrollbar, and I am not sure why. I could overcome this by using overflow-y: hidden;.

It adds a vertical scrollbar to ul because you added margin-bottom: -1px; to it's child (li) and it overflows Y axis.

I don't know how to fix horizontal scrollbar but i think you can fix it with a javascript carousel like owlcarousel, slick carousel etc.

Here is the updated JSFiddle: https://jsfiddle.net/Lh8nfj71/

  • Related