Reputation: 1297
I'm trying to create a menu that can contain an undefined amount of objects; said objects' sizes are dependent on the available width (the width of the menu). The menu's height should never exceed certain value and still contain all the child objects, meaning that the child elements can shrink, while maintaining proportions, but never overflow the "containment area".
Something like this:
add = () => {
const menuObject = document.createElement('div')
menuObject.classList.add('menu-element')
const menu = document.getElementById('menu')
menu.appendChild(menuObject)
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
button{
padding: 40px;
}
.bounds{
position: absolute;
border: 2px dashed black;
width: 10%;
right: 8px;
bottom: 8px;
height: 60%;
box-sizing: content-box;
}
.menu{
position: absolute;
width: 10%;
right: 10px;
bottom: 10px;
background-color: chocolate;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.menu-element{
width: 100%;
background-color: dodgerblue;
margin: 5%;
}
.menu-element::before{
content: "";
padding-top: 100%;
display: block;
}
<body>
<button onclick="add()">Add item</button>
<div class="bounds">
Items should never leave this box
</div>
<div id="menu" class="menu"></div>
</body>
I have tried setting a max-height
attribute to the menu, but that doesn't modify its width which is, ultimately, the value that controls the whole sizing schema. I'm looking for a CSS only solution, if it's at all possible, and any light that can be shed on the issue will be greatly appreciated.
Upvotes: 0
Views: 246
Reputation: 655
If you want the menu to be contained by some bounds, it should be placed within these bounds so it can expand into them.
As the menu is display: flex
, we can have child elements share the available space within the menu by adding flex: 1
to them.
We can optionally add a max-height
value to the menu items if we want to.
add = () => {
const menuObject = document.createElement('div')
menuObject.classList.add('menu-element')
const menu = document.getElementById('menu')
menu.appendChild(menuObject)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
button {
padding: 40px;
}
.bounds {
position: absolute;
border: 2px dashed black;
width: 10%;
right: 8px;
bottom: 8px;
height: 60%;
box-sizing: content-box;
}
.menu {
width: 100%; /* Expand into boundaries */
height: 100%; /* Expand into boundaries */
background-color: chocolate;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.menu-element {
flex: 1; /* Makes elements expand into available space */
max-height: 25%; /* Height cap in case we want to have a set initial size */
width: 100%;
background-color: dodgerblue;
outline: 1px solid red; /* Help visualize boundaries */
}
<button onclick="add()">Add item</button>
<div class="bounds">
<div id="menu" class="menu"></div> <!-- Move menu into boundaries -->
</div>
Upvotes: 1
Reputation: 885
Set the container div's overflow to overflow: auto
.bounds { overflow: auto; } // for example
This will give scroll bars should the items inside exit the container borders.
Also, the flex-shrink
property specifies how the item will shrink relative to the rest of the flexible items inside the same container. If the element is not a flexible item, the flex-shrink property has no effect.
Set element flexible with display: flex;
flex-shrink: number|initial|inherit; // Syntax
for example if you had flexible paragraphs:
p:nth-of-type(2){flex-shrink: 3;} //Second flex-item shrinks 3x more than the rest
number = A number specifying how much the item will shrink relative to the rest of the flexible items. Default value is 1.
initial = Sets this property to its default value.
inherit = Inherits this property from its parent element.
https://www.w3schools.com/CSSref/css3_pr_flex-shrink.asp flex-shrink guide
https://www.w3schools.com/CSSref/pr_pos_overflow.asp overflow guide
Upvotes: 0