Overflow with flex-basis and min and max-width - html

My goal is to use flexbox to implement a slider that has a given width and can grow as items(images) are added into it, until a specific width is reached. After that width is reached i want to show a scrollbar on the x axis. I also want the slider not to shrink bellow the min-width.
This is what i tried:
HTML:
<div class="wrapper">
<div class="thisDivAllowsSliderToGrowToMaxWidth">
<div class="slider">
<div class="image"></div>
...
</div>
</div>
</div>
CSS:
.wrapper {
height: 400px;
display: flex;
justify-content: center;
align-items:center
}
.slider {
display:flex;
justify-content:flex-start;
height:100px;
flex-basis: 250px;
min-width:200px;
max-width:350px;
overflow-x:auto;
}
.image {
flex-shrink:0;
height:100px;
width:50px;
}
The issue that pops out is that as soon as overflow-x is added to the slider, it does not grow anymore but shows the scrollbar as soon as flex-basis width is reached.
Interestingly, adding a simple wrapping div (.thisDivAllowsSliderToGrowToMaxWidth) around the slider somehow fixes the issue. You can find the example here.
Can anyone answer why is this happening and am I using the flex properties as intended?

To make the flex container grow based on the width of the flex items, you can set the flex-basis to content
content will automatically size based on the flex item's content
$(".add-slide").on("click",function(){
$(".slider").append('<div class="image"></div>');
});
.wrapper {
height: 300px;
border :1px solid red;
display: flex;
justify-content: center;
align-items:center
}
.slider {
display:flex;
border: 1px solid black;
height:100px;
flex-basis: content;
min-width:200px;
max-width:350px;
overflow-x:auto;
overflow-y:hidden;
}
.image {
flex-shrink: 0;
border: 1px solid green;
height:100px;
width:50px;
}
button {
margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="add-slide">add slide</button>
<div class="wrapper">
<div class="slider">
<div class="image"></div>
</div>
</div>

Related

Using flexbox, how to overlay an image and expand to fill parent container

In the following html I want the txt-box div to be centered in the container, overlay the image, and expand to fill the container. It should have a margin of equal width on all sides allowing part of the image to show like a thick border.
The html shown is passable for what I want except the vertical vs. horizontal margins are always slightly different as the browser window is resized.
I feel like what I have here is a hack and that I am using flex-grow incorrectly. I understand flex-grow works to allow the txt-box div to expand since it is the only element with a grow value. If I can get that resolved I should be able to simply set a margin on txt-box and it should work.
What am I not understanding about flex-grow?
.container {
display: flex;
align-items: center;
justify-content: center;
border: solid 2px red;
position: relative;
}
.container img {
width: 100%;
flex-grow: 0;
flex-shrink: 0;
}
.txt-box {
background-color: white;
display: flex;
padding: 5px;
border: solid 2px blue;
flex-grow: 1;
position: absolute;
width: 90%;
height: 80%;
}
<div class="container">
<img src="blocks.png" />
<div class="txt-box">
hello world
</div>
</div>
Thanks to Michael Benjamin for putting me on the path to enlightenment. I finally got it figured out. My original question was actually a portion of what I was trying to accomplish. The answers are to use background-image:url('...') and make sure the table and row elements are display:flex.
JSFiddle
<html>
<head>
<style>
.flex-table {
flex-flow:column;
}
.flex-row {
flex-flow:row;
}
.container {
align-items: center;
justify-content: center;
padding: 20px;
border: solid 2px red;
background-image:url('https://i.imgur.com/BF3ty6o.jpg');
background-size:cover;
background-repeat:no-repeat;
max-width:500px;
}
.txt-box {
justify-self:stretch;
align-self:stretch;
border: solid 2px blue;
background-color: rgba(192,192,192,0.5);
}
body, .flex-table, .flex-row, .container, .txt-box {
display:flex;
flex-grow:1;
}
#media (max-width: 768px) {
.flex-row {
flex-flow:column;
}
}
</style>
</head>
<body>
<div class="flex-table">
<div class="flex-row">
<div class="container">
<div class="txt-box">
hello world 1
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 2
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 3
</div>
</div>
</div>
<div class="flex-row">
<div class="container">
<div class="txt-box">
hello world 4
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 5
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 6
</div>
</div>
</div>
</div>
</body>
</html>
What am I not understanding about flex-grow?
Flex properties don't work on absolutely positioned children of a flex container.
ยง 4.1. Absolutely-Positioned Flex
Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Therefore, flex-grow: 1 on txt-box is not doing anything. It's just being ignored.
Considering that you want the image simply laying in the background, while the text box has more requirements, I would suggest absolutely positioning the image and leaving the text box in the normal flow.
Then give the text box full width and height, with equal padding on the primary container to keep uniform "margins" across screen sizes.
Here's a demo, with a few extra features to help illustrate the concepts involved.
body {
height: 100vh;
display: flex;
margin: 0;
padding: 10px;
}
.container {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
border: solid 2px red;
}
img {
position: absolute;
height: 100%;
width: 100%;
object-fit: contain; /* also try 'cover' for demo */
}
.txt-box {
z-index: 1;
width: 100%;
height: 100%;
border: solid 2px blue;
background-color: rgba(192,192,192,0.5);
}
* {
box-sizing: border-box;
}
<div class="container">
<img src="http://i.imgur.com/60PVLis.png">
<div class="txt-box">hello world</div>
</div>
jsFiddle demo

align-items : what is the difference between flex-start and Stretch?

can you please tell me align-items : what is the difference between flex-start and Stretch?
.container {
height: 500px;
padding: 10px;
margin: 50px auto;
background: #eee;
display: flex;
align-items: flex-end
}
.container .box {
padding: 10px;
width: 200px;
height: 200px;
background-color: #fff;
}
<div class="container">
<div class="box"></div>
</div>
You will see no difference if you set a height to your element.
stretch
Flex items are stretched such that the cross-size of the item's margin box is the same as the line while respecting width and height constraints.ref
In your case, nothing will happen with stretch because of the height you set.
flex-start
The cross-start margin edges of the flex items are flushed with the cross-start edge of the line. ref
This is simply align the item on the top. Again, nothing will happen visually since it's somehow the default behavior (not the default value).
.container {
display:inline-flex;
width:200px;
height:200px;
border:2px solid;
}
.container > span {
width:100px;
height:100px;
background:red;
}
<div class="container" style="align-items:flex-start">
<span></span>
</div>
<div class="container" style="align-items:stretch">
<span></span>
</div>
Now remove the height constraint and you will see the difference:
.container {
display:inline-flex;
width:200px;
height:200px;
border:2px solid;
vertical-align:top;
}
.container > span {
width:100px;
min-height:100px;
background:red;
}
<div class="container" style="align-items:flex-start">
<span></span>
</div>
<div class="container" style="align-items:stretch">
<span></span>
</div>

Alignment issue with flexbox in css

I want to align menu on the left side and page content which has multiple dashboard panels/cards on the right side. The problem is dashboard panels/cards are dynamic sometimes number of cards might be 1 and sometimes more than 1. I want all the dashboard panels on the right side to be center aligned.
I tried with the following code but its not working as expected:
main {
display: flex;
flex-wrap: wrap;
}
aside {
width: 200px;
height: 200px;
border: 2px solid red;
}
.flex-items {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.flex-item {
margin-left: 50px;
border: 2px solid red;
flex: 1;
width: 250px;
height: 100px;
}
<main>
<aside>Menu</aside>
<section class="flex-items">
<div class="flex-item">item1</div>
<div class="flex-item">item2</div>
<div class="flex-item">item3</div>
</section>
</main>
Codepen
Finally, I would like to have all the items to be responsive when page is shrunk.
I removed the flex: 1; attribute from .flex-item as it looks like you wanted them to be a specific size. width and flex don't make sense used together as flex: 1; enables flex-grow and that tells the div to use all available space.
I then added flex-grow: 1; to .flex-items so it uses all the available space (before it was just as wide as it needed to be) so the justify-content: center can do it's work.
main {
display:flex;
}
aside {
width:200px;
height:200px;
border:2px solid red;
}
.flex-items {
display:flex;
justify-content:center;
flex-wrap:wrap;
flex-grow: 1;
}
.flex-item {
margin-left:10px;
border:2px solid red;
width:80px;
height:100px;
}
<main>
<aside>Menu</aside>
<section class="flex-items">
<div class="flex-item">item1</div>
<div class="flex-item">item2</div>
<div class="flex-item">item3</div>
</section>
</main>
Note: I changed the widths and margins to allow better rendering in small spaces

FlexBox - container width not expanding when using percent margin [duplicate]

This question already has answers here:
Why doesn't percentage padding / margin work on flex items in Firefox and Edge?
(2 answers)
Closed 5 years ago.
I built a simple page using FlexBox CSS, and I don't understand why when I use a percent margin on one of the items, the width of the container is not expanding.
Note: Problems exists in Chrome / FireFox.
Code Pen: https://codepen.io/dsomekh/pen/QvGvrq
Example:
<html>
<style>
.page{
display:flex;
/*border: 5px solid orange;*/
}
.container{
display:flex;
border: 5px solid orange;
}
.item_left{
display:flex;
margin-right:25%;
}
.item_right{
display:flex;
}
</style>
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
</html>
You're using flexbox wrong.
try
.container{
display:flex;
}
.item_left {
flex: 1;
border: 5px solid orange;
margin-right:25%;
}
.item_right {
flex: 1;
border: 5px solid orange;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
As Michael Coker commented, Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in different browsers. (CSS Flexbox margins)
When using percent we often relate that to the viewport width, so with that in mind, viewport units vw/vh can be a good option, since it works similar (responsive).
Stack snippet made of your Codepen sample
.page {
display: flex;
/*border: 5px solid orange;*/
}
.container {
display: flex;
border: 5px solid orange;
}
.item_left {
flex: 1;
margin-right: 25vw;
}
.item_right {
display: flex;
flex: 1;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
Stack snippet made of your questions code
.page {
display: flex;
/*border: 5px solid orange;*/
}
.container {
display: flex;
border: 5px solid orange;
}
.item_left {
display: flex;
margin-right: 25vw;
}
.item_right {
display: flex;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>

How to center a group of left-aligned divs?

What I'm trying to achieve is to have items one below another in same starting line but to be centered in div. This is my fiddle: https://jsfiddle.net/7vdbLcL9/
<div class="container">
<div id="wrapper">
<div id="inner1">Zmaja od Bosne 5</div>
<div id="inner2">71 000 Sarajevo</div>
<div id="inner3">Bosnia and Herzegovina</div>
</div>
</div>
And the CSS:
.container{
width:40%;
border:1px solid black;
}
#wrapper{
margin-left:auto;
margin-right:auto;
height:auto;
width:auto;
text-align:center
}
I want to get this :
----------------------------------
Zmaja od Bosne 5
71 000 Sarajevo
Bosnia and Herzegovina
----------------------------------
You mean like this? https://jsfiddle.net/7vdbLcL9/1/
Your .container gets text-align:center,
and the #wrapper gets display:inline-block (so that it will be only as wide as needed, and can be centered via text-align of the parent) and text-align:left to counter the effect of center on the parent element.
Just use a flexbox:
.container {
display: flex;
flex-direction: column;
align-items: center;
width:40%;
border:1px solid black;
}
#wrapper { }
DEMO
Flexbox benefits:
minimal code; very efficient
centering, both vertically and horizontally, is simple and easy
equal height columns are simple and easy
multiple options for aligning flex items
it's responsive
it's the future of CSS layouts
Note that flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, post your CSS in the left panel here: Autoprefixer.
.container{
width:40%;
border:1px solid black;
display:flex;
}
#wrapper{
margin-left:auto;
margin-right:auto;
height:auto;
width:auto;
text-align:center
display:flex;
}
Are you looking for something like this?
#wrapper {
display: block;
text-align: center;
line-height: 0;
font-size: 0;
margin-bottom: 20px;
}
#wrapper div {
display: inline-block;
width: auto;
}
#wrapper2 {
display: table;
}
#wrapper2 div {
display: table-cell;
width: 1%;
}
div div {
width: 200px; line-height: 100px; background: lightseagreen; font-size: 12px;
border: 1px solid yellow;
text-align: center;
padding: 0 1em;
}
<div id="wrapper">
<div id="inner1">Zmaja od Bosne 5</div>
<div id="inner2">71 000 Sarajevo</div>
<div id="inner3">Bosnia and Herzegovina</div>
</div>
<div id="wrapper2">
<div id="inner1">Zmaja od Bosne 5</div>
<div id="inner2">71 000 Sarajevo</div>
<div id="inner3">Bosnia and Herzegovina</div>
</div>