How to fix 'overflow: auto' not working as intended? - html

I have made an unsorted list that contains tabs that get created dynamically based on the value of my amount input field. The div of this list has its overflow set to auto to create a scrollbar when too many tabs are created. But for some reason the overflow auto doesn't work as intended.
These pictures show that I can fit a maximum of 21 tabs without a scrollbar. However, as I increase the amount of tabs they get squished together until the 24th tab and only after the 25th has been added the scrollbar appears. (The borders are for visualization purposes and show the dimensions of the div that contains the list as well as the div that contains that div)
These are the respective sections of my HTML and CSS:
#amount-and-tabs-container {
display: flex;
}
.container {
width: 50%;
display: inline-block;
}
#amount-container {
width: 10%;
min-width: 75px;
}
#tabs-container {
width: 100%;
overflow: auto;
border: 1px solid blue;
}
#tabs {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid red;
}
.tab {
cursor: pointer;
text-align: center;
font-weight: bold;
padding: 10px;
margin-left: 20px;
width: 24px;
min-width 24px;
background-image: url("tab.png");
background-size: 100% 100%;
}
.tab.active {
background-image: url("tab_active.png");
}
.tab:hover {
background-image: url("tab_hover.png");
}
<div id="amount-and-tabs-container">
<div class="container" id="amount-container">
<label id="amount-label" for="amount">Amount:</label>
<input type="number" id="amount" value="1" min="1">
</div>
<div class="container" id="tabs-container">
<ul class="tabs" id="tabs"></ul>
</div>
</div>
I have tried to add a width and min-width to the tabs, but it doesn't do anything in regards to this problem. I suspect the cause to be the margin on the tabs, but I am not sure. My leading theory is that the margin gets prioritized above the width.
Answer:
'flex-shrink: 0' fixed this.

Related

Flex-grow takes up its own margin as well when scrolling is needed

I have a container, in my case the body and html tags are the containers. And then I have 3 divs in them and I want the last one to fill the remaining vertical space available while still having a margin.
The third div is generated dynamically so I can't predict what height it's gonna need. The problem is, if it grows too much and a scrollbar is required, the bottom-margin it used to have goes away too. If a scrollbar is NOT required and doesn't appear, the margin is still there and everything looks like I want it to.
I tried to draw what I meant as best as I could in the above image. The 1st case is what I want to happen all the time, regardless of whether there's a scrollbar or not. The 2nd picture is what actually happens, the blue div loses its bottom margin, despite having it set.
Here's my CSS for the html and body tags (they contain the 3 divs, including the blue one):
html,
body
{
width: 100%;
height:100%;
margin: 0px;
padding: 0px;
display: flex;
flex-direction:column;
align-items: center;
background: #494d5f ;
}
and here's my code for the 3rd div, the blue one:
.bottomDiv
{
display:flex;
flex-direction:column;
background: #a0d2eb ;
align-items: center;
width: 97%;
margin-bottom:1.5%;
flex: 1 1 auto;
padding-top:1%;
padding-bottom:1%;
}
Maybe I didn't clarify well enough but the 3rd div in my case, the blue one grows just like it should, fully obeying its margins UNTIL a scrollbar appears and is needed. No matter the amount of growth it has to do, it does it perfectly while respecting its margin. But if it has to grow "out of bounds" of the page so to say, as in, a scrollbar is needed to display all the webpage then its margin is simply gone. IF there is NO scrollbar, everything looks perfect.
Just change this line: body { height: 100%; } to: body { min-height: 100vh; }.
With that line the body will have a height of at least the screen height (100vh) but allows i proper overflow as it is allowed to eb alrger then the screen. As such the margins wont get removed.
html,
body {
width: 100%;
min-height: 100vh;
margin: 0px;
padding: 0px;
display: flex;
flex-direction: column;
align-items: center;
background: #494d5f;
}
.topDiv,
.midDiv {
width: 97%;
height: 50px;
}
.topDiv {
margin-top: 1.5%;
background-color: red;
}
.midDiv {
background-color: blue;
}
.bottomDiv {
display: flex;
flex-direction: column;
background: #a0d2eb;
align-items: center;
width: 97%;
margin-bottom: 1.5%;
flex: 1 1 auto;
padding-top: 1%;
padding-bottom: 1%;
}
#height:checked + label::after {
content: "";
display: block;
height: 150vh;
}
<div class="topDiv"></div>
<div class="midDiv"></div>
<div class="bottomDiv">
<input type="checkbox" id="height" name="height">
<label for="height">checkmark me to extend box height</label>
</div>
I've put an example, so you may try this approach:
body,
html {
margin: 0;
padding: 0;
}
#page {
display: flex;
flex-direction: column;
height: 100vh;
outline: 1px solid purple;
}
#header {
height: 30px;
outline: 1px solid red;
}
#middle {
flex-grow: 1;
/* height: 100vh; */
/* flex-direction: column; */
outline: 1px solid green;
}
#footer {
outline: 1px solid blue;
}
<div id="page">
<div id="header">...</div>
<div id="middle">...</div>
<div id="footer">...</div>
</div>
Try to remove #footer and see that #middle fills the entire screen till the end.
In addition if you need any margins so you have to modify the container like this: #page { ..., margin: 10px; height: calc(100vh - 20px); }

How to get text input that has been rotated by 90 degrees to take up full height of div

I can't seem to work out how to get my input to take up the whole height of the parent div when its rotated (i.e. I want some one to be able to type as much text in as will fit in the parent div.
I've tried changing both the width and height values of the input to 100% and it doesn't help.
I have it working when the input is not rotated, so there must be some sort of trick I am missing?
HTML
.Yaxis-Label-Container {
grid-area: Yaxis-Label;
display: flex;
align-items: center;
justify-content: end;
width: 100px;
height: 1000px;
}
#yaxisLabel {
width: 100%;
height: 29px;
margin: 0 0 0 5px;
background: transparent;
color: #000000;
border: none;
outline: none;
font-size: 16px;
text-align: center;
transform: rotate(-90deg);
}
<div class="Yaxis-Label-Container" >
<input
type="text"
autocomplete="off"
placeholder="Yaxis"
id="yaxisLabel"
/>
</div>
I've ran into this problem as well. All you have to do is use viewport width(vw) and viewport height(vh)
input {
width: 100vw;
height: 100vh;
}
or just try using an id selector if for some reason that selector won't work
#input {
width: 100vw;
height: 100vh;
}
*You won't use 100vw and 100vh you'd have to adjust it to fit the div element, but I can't get it to work any other way.
With your html and css and rotating the div instead of the input it will become this css
.Yaxis-Label-Container {
border: 1px solid red; /*remove this line, for test only*/
grid-area: Yaxis-Label;
display: flex;
align-items: center; /* input will center in width 1000px */
width: 1000px;
height: 100px;
margin-top: calc(0.5 * (1000px - 100px)); /* half of width minus height */
transform: rotate(-90deg);
}
#yaxisLabel {
box-sizing: border-box;
width: 100%;
height: 29px;
margin: 0;
background: transparent;
color: #000000;
border: 1px solid transparent;
outline: none;
font-size: 16px;
text-align: center;
}
<div class="Yaxis-Label-Container" >
<input
type="text"
autocomplete="off"
placeholder="Yaxis"
id="yaxisLabel"
/>
</div>
In the end I did what bron suggested but found that the yaxis label appeared to be shifted to the left as a result of the rotation
Therefore I had to implement a javascript solution to fix its position on the x co-ordinate
I added a listener to the co-ordinates of the parent div. Everytime it moved (i.e. screen resize) I had to calculate the distance required needed to shift the label element left or right such that it appeared in the right place

How to make a navigation bar always stay at the top of a fixed-position panel that is in the middle of the screen?

I'm attempting to create a layout where there is a menubar, a hovering panel that is centered in the screen, and a menubar at the top of the panel. I can't find a way to do this that results in the panel's menubar both the full width of the panel (and no further) while also not scrolling with the contents of the panel.
Here is the (mostly-anonymized) code:
https://jsfiddle.net/BringerOfMisfortune/0rk79dw2/20/
(If you change the class from navBarContainer2 to navBarContainer1 you will see the other issue)
I have several intertwined issues here. I want the main panel that all of my content goes in in the center of the screen. It's a nested div, something like this:
<div>menu bar</div>
<div>
(the panel)
<div>menu bar</div>
<div>content area</div>
(still the panel)
</div>
Ideally, I want the content area to scroll, but the menu bars and the containing "panel" div to be fixed in their positions. To that end, I have the menu bars and the panel set with position: fixed and the panel area is constrained to be 10% from all sides of the screen.
The first issue starts with the fact that I can't seem to find a way that the content area can actually scroll.
If I were to move the scroll: auto out of the panel's CSS and into that of the content area, it not only now does not scroll at all but the text runs out of the bottom of said panel! This is horribly broken and not what I want. I'm not sure why this happens, because the panel can be made to scroll, but not the div inside the panel's div.
So, I needed a way to make the menu bars stay at the top of the screen and at the top of the panel even when the entire panel is being scrolled (since I can't make subsections of it scroll, as per the above issue). I used position: fixed but THAT interferes with the width of the inner menubar on the panel. Note that it sticks way out the right side of the screen. I think that's because it's properly offset to the left wall of the panel, but is still using the window's width... for some reason. Perhaps I can use a manually-tuned percentage, but I'm not sure what would break when resizing a window or making future changes.
However, if I use anything other than fixed (to avoid the broken menubar extending into infinity on the right of the screen), it scrolls with the text, which is the issue I was trying to avoid!
I thus need either of two things:
A way to make the text (and of course other elements too) inside the content area to scroll if they don't all fit inside the panel at once while the panel doesn't scroll
A way to make the panel's menu bar always stay at the top of the scrolling panel without extending out the side of the page
Please help? I have never seen anyone else attempting what I am here (or my Google-fu is that bad), so I'm having trouble figuring out my options.
To make an element scrollable it has to have a height - otherwise the element just extends
to be the height of whatever is in it.
In this instance we can't know the exact height of the remainder of the panel, but we can use flex to ask that the text be given the height remaining. Put your text into a div which can then take up the remaining vertical space. I have given this div an id of textdiv and have put the additional CSS into #content and #panel as I don't know whether you use the classes elsewhere but of course you could use classes if appropriate.
So the additional CSS is:
#panel {
display: flex;
flex-direction: column;
}
#content {
display: flex;
flex-direction: column;
overflow-y:hidden;
}
#textdiv {
overflow-y: auto;
}
Here is the complete snippet, with navBarContainer1 which solves your other, horizontal overflow, problem.
:root {
--edges: #333;
--footer: #fff;
--bgd: #777;
--button: #333;
--button_hover: #111;
--button_lit: #33aaff;
--selectable: #999;
--selectable_hover: #ddd;
--accent: #33aaff;
--theme_main: #e9f4ff;
--theme_second: #ddd;
--formcolor: #fff;
--inactive: #eee;
}
body{
background-color: var(--bgd);
margin: 0%;
padding: 0;
}
.navBarContainer1{
position: absolute;
background-color: var(--button);
width: 100%;
margin: 0%;
padding: 0;
}
.navBarContainer2{
position: fixed;
background-color: var(--button);
width: 100%;
margin: 0%;
padding: 0;
}
.blockbutton {
display: inline;
margin: 0%;
padding: 0;
}
button{
border: none;
cursor: pointer;
color: white;
text-align: center;
padding: 14px 16px;
margin: 0;
text-decoration: none;
font-size: 16px;
transition: all 0.3s ease;
}
.navButton{
background-color: var(--button);
float: none;
}
.navButton:hover:not(.activeNav) {
background-color: var(--button_hover);
}
.mainButton{
background-color: var(--selectable);
border: 1px solid var(--edges);
}
.mainButton:hover:not(:disabled){
background-color: var(--selectable_hover);
}
.activeNav {
background-color: var(--button_lit);
}
button:disabled{
background-color: var(--inactive);
color: var(--inactive);
}
.overlay{
position: fixed;
top: 10%;
left: 10%;
right: 10%;
bottom: 10%;
border-radius: 15px;
background-color: var(--theme_main);
border: 10px solid var(--edges);
overflow: auto;
}
.mainWindow{
margin-top: 40px;
padding: 20px;
}
.file{
background-color: var(--selectable);
width: 99%;
border: 1px solid var(--edges);
cursor: pointer;
color: black;
padding: 14px 0px;
font-size: 16px;
transition: all 0.3s ease;
}
.file:hover{
background-color: var(--selectable_hover);
}
.upload_form{
background: var(--formcolor);
padding: 0px;
border-radius: 5px;
border: 1px solid var(--edges);
max-width: 600px;
margin: 0px auto;
text-align: center;
}
#footer{
position: fixed;
bottom: 0;
text-align: center;
padding: 15px;
color: var(--footer);
font-size: 16pt;
}
progress::-webkit-progress-bar {
background-color: var(--theme_second);
width: 100%;
border: 1px solid var(--edges);
}
progress::-webkit-progress-value {
background-color: var(--accent);
width: 100%;
}
progress {
background-color: var(--theme_second);
width: 100%;
border: 1px solid var(--edges);
color: var(--accent);
}
.hidden{
display: none;
}
#panel {
display: flex;
flex-direction: column;
}
#content {
display: flex;
flex-direction: column;
overflow-y:hidden;
}
#textdiv {
overflow-y: auto;
}
<div class="navBarContainer1">
<button class="navButton activeNav" onclick="">A</button>
<button class="navButton" onclick="">B</button>
<button class="navButton" onclick="">C</button>
<button class="navButton" onclick="">D</button>
<button class="navButton" style="float:right;" onclick="toggleIssues">E</button>
</div>
<div id="panel" class="overlay" style="display:flex;flex-direction:column;">
<div class="navBarContainer1">
<button class="info navButton" onclick="">W</button>
<button class="info navButton" onclick="">X</button>
<button class="info navButton" onclick="">Y</button>
<button class="info navButton" onclick="">Z</button>
</div>
<div id="content" class="mainWindow">
<form class="upload_form">
<h3 id="friendly_prog">Progress: 50%</h3>
<progress id="sysprog" max="100" value="50"></progress>
<input type="file" class="file" id="file">
<h3 id="status">Status: Reticulating Splines</h3>
<button class="mainButton" type="button" id="start" onclick="">Start!</button>
</form>
<div id="textdiv">
<p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p><p>test</p>
</div>
</div>
</div>
try to set parameters top to 50vh like so:top:50vh .
this will set the distance relative to the viewport

Why is the <a> element inside <nav> losing a couple of pixels in the width?

I am creating a responsive menu for a website, but I have a problem: The a tag (red color) is losing a couple of pixels when defining the 100% width of the div (blue color).
To notice the difference it is necessary to open the link of the Pen, use the Chrome inspector and select the red box. The width is shown with pixels less than 30 (example: 28.72, 27.60, etc.).
I have tried other HTML tags although the result has been the same. Why does it happen and what would be the optimal solution for the tag to keep the width and height at 30px, please?
Here the pen: https://codepen.io/Jnico/pen/RQaEoa
body {
padding: 0;
margin: 0;
}
.menu__container {
width: 100%;
background: black;
padding: 0 5px;
}
.menu {
width: 100%;
max-width: 1024px;
height: 55px;
margin: auto;
display: flex;
align-items: center;
}
.logo {
width: 30px;
height: 30px;
background: red;
display: inline-block;
}
.menu__buttons {
width: 100%;
background: blue;
margin-left: 15px;
display: flex;
justify-content: space-between;
}
.button {
padding: 6px 20px;
border: 1px solid #FFFFFF;
}
<nav class="menu__container">
<div class="menu">
<a class="logo"></a>
<div class="menu__buttons">
<a class="button">Button 1</a>
<a class="button">Button 2</a>
</div>
</div>
</nav>
Because of flexbox..
Add flex: 0 0 auto to your .logo so it doesn't flex at all an it should be fine ;) Also, you don't need display:inline-block there, as it's a flex-item already.
.logo {
width: 30px;
height: 30px;
background: red;
flex:0 0 auto;
}
When i set display to inline-table or table is ok and set 30*30
or you can set flex to 0 0 auto;
Either you can use flex-wrap: wrap to the flex container if you want that the flexible items will wrap if necessary.
Or you have to use flex-basis:30px to the <a>(No need to mention the width) and
flex-grow:1 to the .menu__buttons so that it can take the remaining width...
And remove width:100% from the .menu__buttons...No need
Updated Code
My best alternative was:
.logo {
min-width: 30px
}
Because "min" can be used without interrupting my receptive system with fixed pixels or by adding extensive code.

Is it possible for inline-block element to auto fill the available width?

I have a <div id="content">, which contains <div id="sub-navigation> and <div id="main container">, which themselves are inline-blocks. I would like to be able to make the main container fill the rest of the available page width. Is that possible?
I need columns-strip to expand or shrink based on the number and width of column elements. If the width of the columns-strip exceeds the width of the main container, then a horizontal scroll bar should appear.
* {
margin: 0px;
padding: 0px;
font-size: 10pt;
white-space: normal;
}
#wrapper {
margin: 0px 20px;
background-color: red;
}
#header {
margin: 25px 10px 10px 10px;
height: 50px;
background-color: purple;
color: white;
}
#content {
margin: 10px;
padding: 10px;
font-size: 0pt;
white-space: nowrap;
overflow: hidden;
background-color: white;
}
#sub-navigation {
width: 200px;
height: 150px;
display: inline-block;
vertical-align: top;
background-color: forestgreen;
color: white;
}
#main-container {
padding: 10px;
display: inline-block;
overflow: auto;
background-color: yellow;
}
#columns-strip {
padding: 10px;
font-size: 0pt;
white-space: nowrap;
background-color: mediumturquoise;
}
.posts-column {
margin: 0px;
width: 200px;
height: 200px;
display: inline-block;
vertical-align: top;
overflow: auto;
}
#footer {
margin: 10px 10px 25px 10px;
height: 50px;
background-color: navy;
}
<div id="wrapper">
<div id="header"></div>
<div id="content">
<div id="sub-navigation"></div>
<div id="main-container">
<div id="columns-strip">
<div class="posts-column" style="background-color: lightgray;"></div>
<div class="posts-column" style="background-color: darkgray;"></div>
<div class="posts-column" style="background-color: gray;"></div>
</div>
</div>
</div>
<div id="footer"></div>
</div>
You have to remove the inline-block styles and float the #sub-navigation div. inline-block is not suited for what you are trying to achieve. When you add no display styles, the div element will be the default value which is block, block elements take up all the available space by default. By floating the #sub-navigation element you make it only take up the space required for its contents.
#sub-navigation {
width: 200px;
height: 150px;
float : left;
vertical-align: top;
background-color: forestgreen;
color: white;
}
#main-container {
padding: 10px;
overflow: auto;
background-color: yellow;
}
make sure to add a clear: left element after the #main-container
That's not how inline-blocks are supposed to be used. Best thing to do here is make your navigation box float:left and leave the default display value alone.
If your header, footer and wrapper have specific widths, then yes, you can have your main-container fill the available space. But if you're not specifying widths in your CSS, then you need to determine how big your main-container CAN be based on the rendered width of the containing element (wrapper). The only way to determine that width after the page loads is with javascript. If you want your site to have a dynamic width but still have your content (sub-navigation and main-container) fill the screen, you would either need to use javascript or percentages, and percentages can get ugly when you start looking at varying resolutions of monitors, laptops, etc...
Ever heard of flex box model!!
It is made just for that.
Note in flexbox model all child elements act as flex box model you cant opt out certain things. Which mean if page has navigation and under it content div + side div. You can't make top navigation out of it. Which has implications. So solution is to have all things only that need flex box in one div.