CSS anomaly when using overflow-x for horizontal scrolling navbar - html

I am creating a navbar that will horizontally scroll when it is larger than its parent container.
It has a bottom border on the navbar with a different border color for the active link. Using a negative margin to overlap them works fine but when adding overflow-x: auto; the active color disappears.
Here is a codepen to demonstrate:
https://codepen.io/scottknight/pen/aboxYZY
(uncomment the overflow-x and the active border appears)
<div class="container">
<div class="navbar">
Link One
Link Two
Link Three
Link Four
Link Five
Link Six
Link Seven
Link Eight
Link Nine
Link Ten
</div>
</div>
.container {
width: 800px;
}
.navbar {
display: flex;
/* overflow-x: auto; */
border-bottom: solid;
border-bottom-width: 5px;
border-color: gray;
}
.navlink {
padding: 20px;
flex: none;
margin-bottom: -5px;
}
.navlink.active {
border-bottom: solid;
border-bottom-width: 5px;
border-color: red;
}

As described nicely in this answer to a different question, some combinations with overflow-x and overflow-y are not possible. When you set overflow-x to auto, overflow-y (visible by default) also becomes auto.
Looking at your code, I noticed that due to a negative margin, the navlink border is technically overflowing the containing navbar, so when overflow is visible, it bleeds out of the container and you can see it. When overflow is auto, however, you have to scroll down inside your element to see it.
instead of applying the border to your navbar, try applying it to each navlink and override it with active.
.navbar {
display: flex;
overflow-x: auto;
}
.navlink {
padding: 20px;
flex: none;
border-bottom: 5px solid gray;
}
.navlink.active {
border-color: red;
}

Related

Scrollbar horizontal has not applying CSS

I applied CSS for scrollbar but its not working on horizontal scrollbar. I applied already in CSS file for body::scrollbar but applied only vertical scrollbar in reactjs.
I already applied CSS but its working only on vertical scroll.
Here is an example :
body::-webkit-scrollbar-thumb {
background-color: #000000;
width: 10px;
height: 10px;
border-radius: 10px;
}
Use this for scrollbar
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
Height will give you what you wanted. Change 'px' according to your need.

horizontal scrollbar for div sticking out on one side, but not the other

Background
It is a known problem that divs sticking out beyond the viewport width cause a horizontal scrollbar on the <html> element. This is especially frustrating when using width: 100vw while a vertical scrollbar is active. See e.g. Prevent 100vw from creating horizontal scroll
Observation
I now noticed that this problem only appears on one side/direction!
If the overflow:auto container has direction: ltr;, then elements sticking out to the right will cause a scrollbar, whereas elements sticking out to the left are "cut off" as with overflow: hidden;.
If the overflow:auto container has direction: rtl;, then elements sticking out to the left will cause a scrollbar, whereas elements sticking out to the right are "cut off" as with overflow: hidden;.
I tested this with Brave (=Chromium) on Linux, and Firefox on Linux.
.scrollbox {
margin: 10px;
overflow-x: auto;
}
.direction-rtl {
direction: rtl;
}
.stick-out-left {
border: 10px dotted blue;
background: lightgreen;
/* Change this to margin-right -> no scrollbar.. */
margin-left: -10px;
}
.stick-out-right {
border: 10px dotted blue;
background: lightgreen;
/* Change this to margin-right -> no scrollbar.. */
margin-right: -10px;
}
<div class="scrollbox">
<div class="stick-out-left">
this div is sticking out to the left, causing no scrollbar.
</div>
</div>
<div class="scrollbox">
<div class="stick-out-right">
this div is sticking out to the right, causing a scrollbar.
</div>
</div>
<div class="scrollbox direction-rtl">
<div class="stick-out-left">
this div is sticking out to the left inside an rtl container, causing a scrollbar.
</div>
</div>
Questions
Is this behavior consistent across browsers?
Is there some spec definition or theory to explain this behavior?
EDIT: To clarify: I am not looking for a solution to a specific problem. I am looking for an explanation for the behavior I see in the code snippet above. Why is one side cut off, and the other gives me a scrollbar?
thats because you dont use any width for your div. try this:
.scrollbox {
margin: 10px;
overflow-x: auto;
}
.direction-rtl {
direction: rtl;
}
.stick-out-left {
width: 100vw;
border: 10px dotted blue;
background: lightgreen;
/* Change this to margin-right -> no scrollbar.. */
margin-left: -10px;
}
.stick-out-right {
border: 10px dotted blue;
background: lightgreen;
/* Change this to margin-right -> no scrollbar.. */
margin-right: -10px;
}

Color child elements with border height on hover

I have a parent div with 2 anchor child elements. The parent div has a border, and on hover, I wish to highlight the child anchor tags. Now, I can do this, but the hover doesn't fill up the entire width and height of the border that surrounds the parent div.
.header-info {
max-width: 250px;
padding: 10px;
text-align: center;
font-size: 0px;
margin-top: 10px;
font-size: 15px;
border-radius: 5px;
}
.about-header-container {
width: 240px;
border: 10px solid #027878;
}
.about-header-container>a:hover {
background-color: #027878;
color: white;
opacity: 0.7;
}
<div class='about-header-container header-info' id='about-header'>
<a class='bio-header tablink' href='#bio-dashfolio'>Bio</a>
<a class='timeline-header tablink' href='#timeline-dashfolio'> Timeline</a>
</div>
Here's the fiddle: https://jsfiddle.net/kesh92/3cnxef4h/
On hovering over Bio and Timeline, I want it to highlight to the color #027878 while filling up the appropriate section inside the border without leaving any white spaces between the border and the anchor elements. Thanks in advance!
Update
This is the desired hover effect -
Before hover
When hovering over Bio
Edit: Didn't realised you wanted to fill both the height and width. This one will do the trick:
.tablink {
display: inline-block;
width: 45%;
padding: 5px;
text-align: center;
}
On your .header-info change padding: 5px; to padding: 0 5px;
Working fiddle here: https://jsfiddle.net/cba0cn7n/1/
And use the code below to fill the height only
display: inline-block;
padding: 5px 0;
to your .tablink
What is being done here is removing the padding-top and bottom from .header-info and adding it to the .tablink.

Margin property not working but position property is. Why? [duplicate]

As you can see in this picture, I've got an orange div inside a green div with no top border. The orange div has a 30px top margin, but it's also pushing the green div down. Of course, adding a top border will fix the issue, but I need the green div to be top borderless. What could I do?
.body {
border: 1px solid black;
border-top: none;
border-bottom: none;
width: 120px;
height: 112px;
background-color: lightgreen;
}
.body .container {
background-color: orange;
height: 50px;
width: 50%;
margin-top: 30px;
}
<div class="header">Top</div>
<div class="body">
<div class="container">Box</div>
</div>
<div class="foot">Bottom</div>
You could add overflow:auto to .body to prevent margin-collapsing. See http://www.w3.org/TR/CSS2/box.html#collapsing-margins
What you experience is margin collapsing. The margin doesn't specify an area around an element, but rather the minimum distance between elements.
As the green container doesn't have any border or padding, there is nothing to contain the margin of the orange element. The margin is used between the top element and the orange element just as if the green container would have the margin.
Use a padding in the green container instead of a margin on the orange element.
Use padding instead of margin:
.body .container {
...
padding-top: 30px;
}
Not sure if this will work in your case, but I just solved this with the following CSS properties
#element {
padding-top: 1px;
margin-top: -1px;
}
#element was being pushed down because it's first child element had a margin-top: 30px. With this CSS, it now works as expected :) Not sure if it'll work for every case, YMMV.
You can either add padding-top: 30 on the green box, use relative positioning on the orange box with top: 30px, or float the orange box and use the same margin-top: 30px.
You read this document:
Box model - Margin collapsing
CSS
.body {
border: 1px solid black;
border-bottom: none;
border-top: none;
width: 120px;
height: 112px;
background-color: lightgreen;
padding-top: 30px;
}
.body .container {
background-color: orange;
height: 50px;
width: 50%;
}
Not sure how hackish this sounds, but how about adding a transparent border?

Bottom margin of last child gets hidden when overflow applies

I have a container div which has children anchored to the bottom. The problem is that when the div's overflow scrollbar appears, the bottom margin of the last child gets hidden.
Please see http://jsfiddle.net/TxEAP/3/. At first, there's a correct margin underneath the 1 div. Clicking "append one" so that the scrollbar eventually appears makes the last div not have a bottom margin anymore. Opening DevTools shows that the margin of that last child is there, but it is outside of the container's viewport, even when scrolling completely to the bottom.
How can this be solved? It would suffice to get this working in Google Chrome.
HTML:
<div class="main">
<div class="container">
<div class="item">1</div>
<!-- several of these .item divs -->
</div>
</div>
CSS:
.main {
height: 200px;
overflow-y: scroll;
position: relative;
border: 1px solid black;
}
.container {
width: 100%;
max-height: 100%;
position: absolute;
bottom: 0;
}
.item {
padding: 20px;
margin: 15px;
border: 1px solid black;
}​
Here's my final solution using flexbox. It's supported well enough on Chrome despite all -webkit- prefixes. Basically, the idea is to have a dummy element that, in case of no overflow, fills up the space of the container starting from the top (so that the real children are anchored to the bottom); in case of overflow, it is hidden automatically because of height: 0. It does not suffer from the margin issue, and it does not collapse margins.
http://jsfiddle.net/mCYLm/1/
HTML:
<div class="main">
<div class="gap-filler"></div>
<div class="item">foo</div>
<!-- more `div.item`s -->
</div>
CSS:
div.main {
display: -webkit-box;
-webkit-box-orient: vertical;
height: 200px;
overflow-y: scroll;
}
div.main div.gap-filler {
-webkit-box-flex: 1;
height: 0;
}
div.main div.item {
border: 1px solid black;
margin: 20px;
padding: 20px;
}​
Edit: This was a solution without flexbox, but it had selection issues.
A solution that eventually worked was the following: http://jsfiddle.net/TxEAP/7/. This appends hidden "content" which makes Chrome not hide the margin of the last .item div.
.container:after {
content: "";
font-size: 0;
display: block;
height: 1px;
}
Edit: The following only works if display: inline-block is possible.
Finally I found a solution. If all .items have display: inline-block except the first one, then the margin does not get hidden.
http://jsfiddle.net/TxEAP/5/
.item:not(:first-child) {
display: inline-block;
/* attempt at getting `width: auto` like `display: block` has */
width: -webkit-calc(100% - 2 * 15px);
box-sizing: border-box;
}
If you just move the overflow-y: scroll; from .main. to .container class then the margin is preserved. The only drawback is for less than 3 items (for the given container height) you get a small scrollbar placeholder, instead of a full height one.
Removing max-height:100% on the container seems to fix it for my test in Chrome 21.
Moving the properties so that the overflow is on the container, preserves the margin/padding for an element added to the end that results in the scrollbar appearing.
.main {
height: 200px;
border: 1px solid black;
}
.container {
width: 100%;
height: 100%;
overflow-y: scroll;
}