I am trying to implement a CSS "card template" that a 2 item flexbox that needs wrap the last item when the first item is at a certain width. To complicate matters the width of the last item can be variable. This makes more sense when you view the JFiddle below. The green box is the first item, and the red box is the last item. The red box needs to wrap to the next line when the user changes the windows size to where the green box reaches a width of 300px. I've tried to use the flex-wrap combined with min-width, but this doesn't do the trick. Any help is appreciated.
https://jsfiddle.net/burtonrhodes/tu4wgc3m/41/
And below is an example of the card template
<div class="afs-card">
<div class="afs-card-checkbox">
<input type="checkbox" />
</div>
<div class="afs-card-icon">
X
</div>
<!-- this div should expand to fill the space -->
<div class="afs-card-info">
<!-- this item should exapnd to fill the space -->
<div class="afs-card-content">
<div class="afs-card-description">
This is the content for the card. When adjusting the screen, if this box is
<=3 00px;, then the red box should wrap to the next line. </div>
<div class="afs-card-sub-description">
This is a sub text for the card
</div>
</div>
<!-- this div will be a certain width based off child width properties
and should go to next line if afs-content's width is <= 300px -->
<div class="afs-card-details">
<!-- no wrapping of these items should occur -->
<div style="width: 80px">
10/15/2005
</div>
<div style="width: 20px">
X
</div>
<div style="width: 70px">
More
</div>
</div>
</div>
<div class="afs-card-menu">
...
</div>
<div class="afs-card-drag-handle">
==
</div>
</div>
You can achieve this using flex-basis and flex-grow. Update your css with this:
// Your wrapper
.afs-card-info {
display: flex;
width: 100%;
border: 1px solid;
flex-wrap: wrap;
}
// Your left container
.afs-card-content {
padding: 1px 10px;
border: green 2px solid;
flex-basis: 300px;
flex-grow: 1;
}
you can do it like this without media queries:
.afs-card-info {
display: flex;
flex-wrap: wrap;
width: 100%;
border: 1px solid;
.afs-card-content {
flex-grow: 1;
min-width: 300px;
flex-basis: calc(100% - 176px);
set the container to wrap
set the content to fill available space
set content minimum width to ensure it will force the wrap eventually
flex-basis sets the elements width prior to any flex space distribution, so setting it to the rows space less the second element width prevents it from always wrapping the second element
fiddle: https://jsfiddle.net/z91j04rh/4/
place this line of code above the css that you want to apply the 300px min-width to
#media only screen and (min-width: 300px) {
#elementid {
--css here--
}
}
Related
The following threads were not helping with my situation:
How to make bootstrap column height to 100% row height? [duplicate]
CSS - div extend height to match sibling
Make a div fill the height of the remaining screen space
I am populating the column's content by a for loop and I don't know the height for the column with the highest content.
I want to make the sibling columns to automatically fit to the highest column height and within the column it has a few rows of data where I would want them to have equal height as well when they are being stretched to fit the highest column.
How can I achieve this?
Here's a sample picture for my current situation:
Essentially, I want to achieve the following:
Here's my component.html:
<div class="container">
<div class="row">
<div class="col-4">
<div *ngFor="let element1 of level1" style="min-height: 20px; border: 1px solid black;">
{{element1}}
</div>
</div>
<div class="col-4">
<div *ngFor="let element2 of level2" style="min-height: 20px; border: 1px solid black;">
{{element2}}
</div>
</div>
<div class="col-4">
<div *ngFor="let element3 of level3" style="min-height: 20px; border: 1px solid black;">
{{element3}}
</div>
</div>
</div>
</div>
and my componenet.ts where I'm instantiating the string array to populate my column:
export class AppComponent {
name = "Angular";
level1: string[] = ["1A"];
level2: string[] = ["2A", "2B", "2C"];
level3: string[] = ["3A", "3B", "3C", "3D", "3E"];
}
I tried setting max-height: fit-content to my row and height: 100% to my content <div> but it didn't work.
I think you can achieve this by using flexbox, by adding the following css:
.row {
display: flex;
}
.col-4 {
display: flex;
flex-direction: column;
> div {
flex-grow: 1;
}
}
flex-grow will make sure the elements will fill up the remaining heights.
so add this to all the div elements, and they will behave as you want them to
This question already has answers here:
How to match width of text to width of dynamically sized image/title?
(2 answers)
Closed 3 years ago.
I have a fixed-position container element with two children. Both children contain text. I want one of the children to dynamically set the width of the container with its content. I want the other child's text to wrap appropriate based on that width.
For example:
.container {
position: fixed;
}
.wrap {
background: red;
}
.stretch {
background: green;
}
<div class="container">
<div class="wrap">
this text is very very long
</div>
<div class="stretch">
shorter text
<div>
</div>
In this example, I would like the container's width to match the shorter green .stretch div. I want the red .wrap div to have the same width, with the text wrapped inside, like:
The solution's come up with me was:
The child div needs to stretch its width depends on its content -> max-content
The parents's width needs to be as shrink as possible depends on its content -> min-content
The solution code with variant bahaviors:
.container {
width: min-content;
border: 2px solid blue;
margin: 5px;
}
.wrap {
background: red;
width: auto; /* default btw */
}
.stretch {
background: green;
width: max-content;
}
<div class="container">
<div class="wrap">
this text is very very long
</div>
<div class="stretch">
shorter text
</div>
</div>
<div class="container">
<div class="wrap">
shorter
</div>
<div class="stretch">
shorter text
</div>
</div>
<div class="container">
<span class="wrap">
shorter
</span>
<div class="stretch">
shorter text
</div>
</div>
You can read more about min-content and max-content from this answer or the specification.
max-content inline size: the narrowest inline size it could take while fitting around its contents if none of the soft wrap opportunities within the box were taken.
min-content inline size: the narrowest inline size a box could take that doesn’t lead to inline-dimension overflow that could be avoided by choosing a larger inline size. Roughly, the inline size that would fit around its contents if all soft wrap opportunities within the box were taken.
I'm using bootstrap, with the following html:
<div class="container-fluid h-100">
<div class="row align-items-center h-100">
<div class="col-md" align="center">
<h2>Login</h2>
<form>
<table>
<tbody>
</tbody>
</table>
<button type="submit">Login</button>
</form>
</div>
<div class="col-md-auto h-100 d-none d-md-flex">
<div class="vertical_divider"></div>
</div>
<div class="col-md" align="center">
<div class="signup_button"><p>Signup</p></div>
</div>
</div>
</div>
With the following relevant css:
.page_content {
border: 3px solid orange;
border-radius: 20px;
padding: 30px;
height: 75vh; #Changing this to 'auto' makes the vertical divider disappear
max-height: 75vh;
overflow-y: scroll;
}
.vertical_divider {
position: relative;
height: 100%;
width: 0;
border: none;
border-right: 3px solid $bordercolour;
}
Fiddle: https://jsfiddle.net/aq9Laaew/176561/
This makes a div that is always 75% of the viewport height, regardless of its content. This works perfectly.
I want to modify it so that the div is only as big as its contents, up to a maximum of 75vh. If the content is bigger than that, the overflow should scroll within the div. I've done this by changing the height attribute of the page_content class to auto. This works, except that it makes the central orange line disappear (this happens in the fiddle too, if you change the setting).
Why does this happen? h-100 should make the column containing the vertical divider 100% of the row, and yet it doesn't. I've tried making various styles !important, but that didn't make any difference.
Why does this happen?
Because a percentage height only works when the parent element has a set height, with the exception of the html tag. When you set .page_content height to auto, there is no longer a set height on the parent element of the divider, and thus a percentage height does nothing.
To make it work you either need to ensure that the parent element chain all the way until html has a set height (i.e. not auto). Or as an alternative solution, if your middle column has no other purpose than the divider line, the whole column is kind of pointless since you can just create the line as a CSS border of one of the two other columns.
I am using ZURB foundation 6 with XY grid and have run into a little problem and most likely something I'm doing wrong.
I want to center elements vertically so I use
<div class="flex-container">
<div class="grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>
And using jQuery I set the height of flex-container by using windowHeight = $(window).innerHeight();
Voila the items are vertically aligned... However two issues arise from this:
small-6 cell has a width of 50% that is not being respected and shrinks down to the approx length of the text.
flex-container unlike grid-container does not have a width or padding.
To resolve the issue I added some CSS like so:
.flex-container .align-middle {
max-width: 62.5rem;
margin: 0 auto;
width: 100%;
}
So while I've patched the issue I can't help thinking that there must be an easier way, a proper way using just classes. It seems odd that grid-container is setup to do so but flex-container is not.
The main problem here is that with flex-container, the grid-x element will, along being a flex container of its own, also become a flex row item, having the default flex item value 0 1 auto.
This means the grid-x won't grow wider than its content, hence width: 50% won't work on its children (small-6), as their parent doesn't have a width set.
By adding e.g. flex-child-grow or cell to the grid-x element, it will fill its parent's width, and the inner flex items will start behave as expected.
Note 1: With grid-container this is not needed since it is not a flex container, where the grid-x is a normal div, displayed as flex, which, like a block element, by default take full width of its parent.
Note 2: Both flex-container and grid-container does have a default width of 100%, it is the grid-x, when being a flex item, that cause the issue not taking its parent's width by default.
Stack snippet
/* for demo purpose */
body { margin: 0; }
.flex-container { height: 100vh; }
.grid-x { border: 1px solid red; }
.small-6 { border: 1px solid blue; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.css" rel="stylesheet"/>
<div class="flex-container">
<div class="flex-child-grow grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>
I'm reproducing a golden spiral using CSS flexbox and percentage size for cells.
The round shape is drawn using a regular border and border-radius combination.
Everything is proportional until I resize the window to smaller widths.
I tried removing borders completely and turns out the layout is still losing proportions at some point.
Big container:
Small container:
Demo:
https://jsfiddle.net/s09rkwub/1/
html
<div class="wrapper">
<div class="rows fib">
<div class="cols fill">
<div class="rows fill">
<div class="fr tl">3</div>
<div class="fill cols">
<div class="fc bl">4</div>
<div class="fill rows">
<div class="fill cols">
<div class="fill tl fr">7</div>
<div class="fc tr">6</div>
</div>
<div class="fr br">5</div>
</div>
</div>
</div>
<div class="fc tr">2</div>
</div>
<div class="fr br">1</div>
</div>
</div>
css
.rows {
flex-direction: column;
}
.cols {
flex-direction: row;
}
.rows,
.cols {
display: flex;
.fill {
flex: 1;
}
> * {
outline: solid 1px rgba(127,127,127, 0.3);
}
}
...
Update:
Working demo with applied solution.
Update 2
Thanks to Your support guys. I could finish my fib spiral codepen.
Solution
Add this to your code:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}
revised fiddle
Explanation
Two concepts to consider:
An initial setting of a flex container is flex-shrink: 1.
This means that, by default, flex items are allowed to shrink below any defined width, height or flex-basis.
To prevent this behavior use flex-shrink: 0.
More details here: What are the differences between flex-basis and width?
An initial setting of a flex item is min-width: auto.
This means that, by default, a flex item cannot be smaller than the size of its content (regardless of flex-shrink or flex-basis).
To allow flex items to shrink past their content use min-width: 0 (row direction), min-height: 0 (column direction), or overflow: hidden (other values also work, except visible).
More details here: Why doesn't flex item shrink past content size?
With the adjustment below, your flex items can shrink past the text you have in your divs, allowing the scaling to continue without any obstacles:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}
Taking <div class="fr br">5</div> as an example, it's min-width is 26px. Thus, scaling the spiral down to a level, where the mentioned div's height becomes less than 26px, it's getting distorted.
If you change the border width to 1px instead of 5px, you'll see, that suddenly, it's able to scale down to 18px perfectly fine and breaks in smaller sizes.
That's why you probably tried to reduce the border. However, the reason for the distortion is much simpler: You have content inside the divs and they do require some space (even if the font color is transparent). If you remove all the numbers from the div elements, you get the desired result. See the demo at https://jsfiddle.net/s09rkwub/2/