Flex box requires width for proper sizing [duplicate] - css

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
What are the differences between flex-basis and width?
(6 answers)
Closed 3 years ago.
Using flex for the main menu that has three boxes. The first and third do not flex, and the second grows to fill. The second box is a nested flex that has two boxes, the first does not flex and the second grows to fill. The nested flex, second box is configured to use ellipsis for overflow, but that did not work. The box expands and pushes the nested flex, but not the parent flex, beyond the parent max width. Then discovered if the second boxe has a defined width, any value, even 1px, it works as expected. Concerned and courious why that is, and if i'm doing something wrong.
Codepin to see in action: https://codepen.io/nws-jholmberg/pen/mdyEyWq
<div class="menu-container">
<div class="menu">
<div class="menu-item-1 menu-item">X</div>
<div class="menu-item-2 menu-item">
<div class="menu-search">
<div class="menu-item-search-1">X</div>
<div class="menu-item-search-2">The search result goes here and does not fit</div>
</div>
</div>
<div class="menu-item-3 menu-item">X</div>
</div>
</div>
<br>
<div class="menu-container">
<div class="menu">
<div class="menu-item-1 menu-item">X</div>
<div class="menu-item-2 menu-item">
<div class="menu-search">
<div class="menu-item-search-1">X</div>
<div class="menu-item-search-2 add-width">The search result goes here and does not fit</div>
</div>
</div>
<div class="menu-item-3 menu-item">X</div>
</div>
</div>
.menu-container {
background-color: #f00;
max-width: 200px;
}
.menu {
display: flex;
}
.menu-item {
margin: 4px;
}
.menu-item-1 {
flex: none;
}
.menu-item-2 {
flex: 1;
background-color: #0ff;
}
.menu-item-3 {
flex: none;
}
.menu-search {
display: flex;
}
.menu-item-search-1 {
flex: none;
background-color: #3A3;
color: #fff;
}
.menu-item-search-2 {
flex: 1;
background-color: #3F3;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.add-width {
width: 1px;
}

there is 2 other hurtless ways you can use :
.menu-item-2 {
flex: 1;
background-color: #0ff;
overflow:hidden;
}
or
.menu-item-2 {
flex: 1;
background-color: #0ff;
min-width:0;
}
https://codepen.io/gc-nomade/pen/yLyJypm

Related

How to arrange intersected sections with variable heights [duplicate]

This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed 11 months ago.
I have a report that has to be in blocks (divs), these divs must be aligned horizontally (with width of 50% for each), meaning that the second is to right of the first, and the third must be below the first one regardless of the height of the second.
My description might be a little fuzzy, so I attached an image that represents the idea:
Sample:
Thank you very much in advance.
I tried normal CSS hacks (float, position, display) and so on; and it didn't work.
I tried grid layout, and I tried to use Bootstrap properties; in all the above, block number 3 starts, yes, below block one but after the end of block number 2 height.
Try this:
.maindiv { /* Masonry container */
column-count: 2;
column-gap: 1em;
}
.item { /* Masonry bricks or child elements */
display: inline-block;
margin: 0 0 1em;
width: 100%;
}
here's a quick way of doing it with flexbox, link to codepen. The downside is that you would need to have 2 columns, so on mobile, the second col would go below the first one. Ideally, you would do this with CSS Grid, or JS Masonry plugin
And here's the code itself:
HTML:
<div class="example-wrap">
<div class="col">
<div class="card" style="height: 100px;"></div>
<div class="card"></div>
<div class="card" style="height: 400px;"></div>
</div>
<div class="col">
<div class="card"></div>
<div class="card" style="height: 400px;"></div>
<div class="card" style="height: 150px;"></div>
</div>
CSS:
.example-wrap {
display: flex;
width: 600px;
justify-content: space-between;
align-items: flex-start;
box-shadow: 0 0 0 1px black;
}
.col {
width: calc((100% - 30px) / 2);
}
.card {
width: 100%;
height: 300px;
box-shadow: 0 0 0 1px red;
margin-bottom: 30px;
}
Masonry is the best way to do what you want.
var elem = document.querySelector('.grid');
var msnry = new Masonry( elem, {
// options
itemSelector: '.grid-item',
columnWidth: 200
});
// element argument can be a selector string
// for an individual element
var msnry = new Masonry( '.grid', {
// options
});
.grid-item {
width: 40%;
margin: 20px;
border: 1px solid black;
height: 100px;
text-align: center;
color: red;
font-weight:700;
}
.height-2 {
height:300px;
}
<script src="https://unpkg.com/masonry-layout#4.2.2/dist/masonry.pkgd.min.js"></script>
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item height-2">2</div>
<div class="grid-item height-2">3</div>
<div class="grid-item">4</div>
</div>
See Masonry for more options/methods : https://masonry.desandro.com/

How to prevent child's content from stretching parent's width [duplicate]

This question already has answers here:
How to match width of text to width of dynamically sized image/title?
(2 answers)
Closed 2 years ago.
I have a component (Container) that contains an icon (marked with an X below), a title and a child component (Message) that contains a long message. I would like Container's width to wrap around the icon and the title so both are on one line as much as window's width allows for it.
Message component has a button that toggles display of a long text. This text should not stretch the parent Container and it should be aligned with title's width. The message content can be broken and wrapped at any point:
I used a flex-grow: 1; width: 0; style on a dummy div in Message as suggested
here to prevent it from growing. This works well on all browsers except for MS Edge, where the message content stretches the parent:
How can I fix this issue on MS Edge?
Is there alternative way using only CSS that I can prevent the message content from stretching its parent?
Style.css:
.box {
display: table;
margin: auto;
border: 1px solid black;
}
.container {
display: flex;
justify-content: center;
}
.icon {
margin-right: 10px;
}
.message {
display: flex;
}
.message > div {
flex-grow: 1;
width: 0;
word-break: break-all;
}
Container.jsx:
export const Container = () => {
return (
<div className='box'>
<div className='container'>
<div className='icon'>
X
</div>
<div className='content'>
<div className='title'>
Some title
</div>
<Message>
Long message that should not make parent wider
</Message>
</div>
</div>
</div>
);
}
Message.jsx:
export const Message = ({children}) => {
const [isExpanded, setExpanded] = React.useState(false);
const handleClick = () => setExpanded(!isExpanded);
return (
<div>
<div>
<button onClick={handleClick}>Click</button>
</div>
{isExpanded &&
<div className='message'>
<div>{children}</div>
</div>
}
</div>
);
}
Try width:0;min-width:100%; on the message container:
.box {
display: table;
margin: auto;
border: 1px solid black;
}
.container {
display: flex;
justify-content: center;
}
.icon {
margin-right: 10px;
}
message {
display:block;
width:0;
min-width:100%;
}
<div class='box'>
<div class='container'>
<div class='icon'>
X
</div>
<div class='content'>
<div class='title'>
Some title
</div>
<message>
<div>Long message that should not make parent wider</div>
</message>
</div>
</div>
</div>
Or to the div inside the message:
.box {
display: table;
margin: auto;
border: 1px solid black;
}
.container {
display: flex;
justify-content: center;
}
.icon {
margin-right: 10px;
}
message {
display:block;
}
message > div {
width:0;
min-width:100%;
}
<div class='box'>
<div class='container'>
<div class='icon'>
X
</div>
<div class='content'>
<div class='title'>
Some title
</div>
<message>
<div>Long message that should not make parent wider</div>
</message>
</div>
</div>
</div>

Multiple siblings, place some in same row & fill extra space

I have no control of the html. I have a parent with multiple children.Only some of them must be in the same row, while the rest of them stay unaffected and one of them must take up all the extra space. Content is auto generated and % is not an option.
Other options except inline to place on the same row to avoid the problem are welcome as well.
.parent {
background: red;
}
.same-row-child {
background: green;
display: inline-flex;
}
<div class="parent">
<div class="other-child">A</div>
<div class="same-row-child">B</div>
<div class="same-row-child">C</div>
</div>
To sum up: Α in the first line unaffected.
B+C in the same line with B taking up all the extra space.
If the idea is to use flex, then it should be the parent the flex box:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
display:flex; display:inline-flex; It enables a flex context for all its direct children.
.parent {
background: red;
display: flex;
flex-wrap: wrap;
}
.other-child {
width: 100%;
}
.same-row-child {
background: green;
}
.parent :last-child {
flex: 1;
margin-left:2px;
}
<div class="parent">
<div class="other-child">A</div>
<div class="same-row-child">B</div>
<div class="same-row-child">C</div>
</div>
looks like not the option you would use See next option
The oldish way is float and overflow, and the one to float is the one that comes first and is supposed to shrink on itself.
see https://css-tricks.com/all-about-floats/
Aside from the simple example of wrapping text around images, floats can be used to create entire web layouts.
.parent {
background: red;
}
.other-child {}
.same-row-child {
float: left;
background: green;
margin-right: 2px;
}
.parent :last-child {
float: none;
overflow: hidden;
margin: 0;
}
<div class="parent">
<div class="other-child">A</div>
<div class="same-row-child">B</div>
<div class="same-row-child">C</div>
</div>

Make an element take up available horizontal space without causing its parent to widen

I have a flexbox container with exactly two children, both of which can have variable content. I want the width of the entire container to fit the width of the first child, but I want the second child's contents to wrap and not cause the container to grow horizontally. See the runnable snippet below for a visual problem description.
Currently looking for a CSS Grid solution. I have found one partial solution, but relies on JavaScript: Make the second child a relative container, put its contents in an intermediate absolutely-positioned container, and use JS to set a fixed height. At least it's good for showing what I'm looking for.
Problem:
.container {
display: inline-flex;
flex-direction: column;
border: 1px solid red;
}
.child {
background-color: wheat;
margin: 5px;
}
<div class="container">
<div class="first child">
This content can grow and be as wide as it wants
</div>
<div class="second child">
This content will also be any size it wants, but I * want it to wrap at the asterisk in this sentence, which is where the first child above would naturally end. This will be its own flexbox container holding several buttons that should wrap onto new rows.
</div>
</div>
JavaScript/absolute solution:
let second = document.getElementsByClassName('second')[0]
let content = document.getElementsByClassName('absolute')[0]
second.style.height = content.offsetHeight + 'px'
.container {
display: inline-flex;
flex-direction: column;
border: 1px solid red;
}
.child {
background-color: wheat;
margin: 5px;
}
.second {
position: relative;
/* height to be set by JS */
}
.absolute {
position: absolute;
width: 100%;
top: 0;
left: 0;
}
<div class="container">
<div class="first child">
This content can grow and be as wide as it wants
</div>
<div class="second child">
<div class="absolute">
This content is longer than the above but still wraps in the right place.
</div>
</div>
</div>
Just set min-width and width of .second:
.container {
border: 1px solid red;
display: inline-block;
padding: 5px;
}
.child {
background-color: wheat;
}
.second {
margin-top: 10px;
min-width: 100%;
width: 0;
}
<div class="container">
<div class="first child">
This content can grow and be as wide as it wants
</div>
<div class="second child">
This content will also be any size it wants, but I * want it to wrap at the asterisk in this sentence, which is where the first child above would naturally end. This will be its own flexbox container holding several buttons that should wrap onto new rows.
</div>
</div>

Make flex item with flexible size keep its size when children overflow [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 5 years ago.
This one is really frustrating me and Im not sure if I worded that correctly.
Basicly, I need my page to stay at 100% height and not grow in height as it is a single page website.
I have a list in an aside and whenever I add content to the list it makes the list grow in size when I need the overflow to be hidden (I have a custom scrollbar applied in react).
Anyhow, the growing (weirdly) only occures when the list has the height of flex: 1;. When I add a fixed height, everything is fine.
Here is how it acts with a fixed height (should also be like this when no fixed height is applied):
When I remove the fixed height of the red box (the list) then it causes itself and the whole page to grow:
See it in action:
Heres the pen to see for yourself: https://codepen.io/anon/pen/zPJdoK
I know theres some unnecassary markup but I needed that to be sure that it represents the actual webpage I am working on.
Sorry for not being able to explain it any more detailed, Im a bit confused as of now...
Are you referring to something like this perhaps? I'm not too sure.
.container{
background: black;
width: 1000px;
height: 300px;
display: grid;
grid-template-columns: 180px 1fr 180px;
grid-template-rows: 1fr;
grid-template-areas: "nav main aside";
}
nav {
grid-area: nav;
background: blue;
}
main {
grid-area: main;
background: black;
display: flex;
flex-direction: column;
}
aside {
grid-area: aside;
background: green;
display: flex;
flex-direction: column;
}
aside > header, aside > footer{
height: 60px;
background: yellow;
}
aside > main {
flex: 3;
background: green;
}
aside > main > .content {
background: red;
margin: 10px;
max-height: 200px;
overflow-y:scroll;
}
.space_taker{
margin: 10px;
height: 30px;
background: white;
}
<div class="container">
<nav></nav>
<main></main>
<aside>
<header>
</header>
<main>
<div class="content">
<div class="space_taker">asdafasdfasdf</div>
<div class="space_taker">asdfasdf</div>
<div class="space_taker">asdfs</div>
<div class="space_taker">dfgdgf</div>
<div class="space_taker">asdasd</div>
<div class="space_taker">asdasd</div>
<div class="space_taker">asdfs</div>
<div class="space_taker">dfgdgf</div>
<div class="space_taker">asdasd</div>
<div class="space_taker">asdasd</div>
<div class="space_taker">asdfs</div>
<div class="space_taker">dfgdgf</div>
<div class="space_taker">asdasd</div>
<div class="space_taker">asdasd</div>
</div>
</main>
<footer>
</footer>
</aside>
</div>

Resources