Flexbox preventing margins from being respected - html

I'm struggling to get a flexbox layout working with margins and overflow: hidden.
The carousel component I'm integrating uses this method to be responsive but as soon as a display:flex is applied to the parent, the margin and overflow: hidden properties are ignored as shown in the example below.
The top version is not nested in a flexbox where as the one below it is, and is not respecting the margins of the parent.
The issue is demonstrated in the code below and in this Plunker.
http://plnkr.co/edit/qU1oq1Vq1X3FQMWLJiQk?p=preview
body {
margin: 400px;
}
.overflowHidden {
overflow: hidden;
}
.flex {
display: flex;
}
<div>
<div class="overflowHidden">
<img src="http://lorempixel.com/600/400" />
</div>
</div>
<div class="flex">
<div>
<div class="overflowHidden">
<img src="http://lorempixel.com/600/400" />
</div>
</div>
</div>
I know there are many similar questions on this topic but I couldn't find anything relating to my particular use case.

Here's the solution:
.flex > div { overflow: hidden }
revised demo
The first thing to note is that margins have nothing to do with this problem. Margins are, in fact, being respected. They are simply travelling with the element, which is expanding a container.
The non-flex div containers have display: block by default.
In a block formatting context, when an image becomes too big to fit in a container with overflow: hidden, it simply disappears, as expected.
The parent divs and their margins remain stable and undisturbed.
However, in a flex formatting context the behavior is different.
First, you have three levels of divs in the flex example. You only have two in the block example. But that's not really important.
The key piece of information here is this:
When you apply display: flex or display: inline-flex to an element it becomes a flex container and its children become flex items. By default, flex items cannot be smaller than the size of their content. They have a default setting of min-width: auto.
So, when an image becomes too big for its parent, the parent (if it's a flex item) must expand. But in your example, the parent of the image (div.overflowHidden) is not a flex item, it's a standard block element. So overflow: hidden is working fine (just like in the block example).
But the parent of the parent is a flex item. And its default setting is min-width: auto. And it cannot shrink below the size of its content (the image). So while the block example can remain on the screen at all times, the flex version will overflow the body / viewport, taking the right margin with it.
The solution is to override the min-width: auto default on the flex item. You can use:
min-width: 0
OR
overflow: hidden
More details here: Why doesn't flex item shrink past content size?

Not sure why that's happening exactly, but seems to work if you apply .overflowHidden to either an element that wraps the flex parent, or just apply it to the flex parent instead.
body {
margin: 400px;
overflow-x: hidden;
}
.overflowHidden {
overflow: hidden;
}
.flex {
display: flex;
z-index: -1;
position: relative;
}
<div>
<div class="overflowHidden">
<img src="http://lorempixel.com/600/400" />
</div>
</div>
<div class="flex overflowHidden">
<div>
<img src="http://lorempixel.com/600/400" />
</div>
</div>
<div class="overflowHidden">
<div class="flex">
<img src="http://lorempixel.com/600/400" />
</div>
</div>

Related

containers with images of different sizes; container width won't go past the image width

I have divs with images in them stacked horizontally side by side of each other. Images are of different widths and heights.
If I make the container width's smaller than the images, all the divs are uniform nicely.
But if I make the width of the container bigger than the images, the div/container width just seems to stop at the size of the image and refuse to get any bigger. What am I doing wrong or am I misunderstanding anything? I'm still learning my HTML and CSS thank you
PS - I don't want to use background: url(...) because I need my image URLs to be dynamic. Unless this is the only way?
.test__container {
width: 800px;
}
.test__img {
width: 100%;
}
<div class="test__container">
<img class="test__img" src='https://via.placeholder.com/350x150/' />
<h1 class="test__name">Davy Crocket</h1>
</div>
It is possible they are inside a flex container (that has display:flex). That makes it treat width property of children differently.
When you create a flex container (display: flex or display: inline-flex), it comes with several default settings. Among them are:... read more
(specifically it forces items to stay on one line [no matter the count])
Give the images a width of 100%. This will make them as wide as their parent, not as wide as their native size.
&__img {
width: 100%;
}
Update (based on added context): if the parent container has a display property of flex, one has to set min-width to 100% on the image. Note: flex-wrap: wrap should also be set on parent, to prevent siblings from creating a horizontal scrollbar on parent.
An alternative solution is to give the image flex-basis of 100% and flex-shrink of 0.
However, flex calculation is dependent on several other CSS attributes of the image as well as on CSS attributes and content of siblings and of parent elements. The safest option for flex remains min-width, as it trumps the result of flex calculation (basically the flex calculation starts from the given min-width and distributes the remaining space, if any, to the flexible siblings).
as you can see from the snippet below wrapping your code in a flexbox container doesn't change anything by itself. There most be either additional css or something else going on.
I edited your original post. You will get help faster if you post snippets here instead of providing a link to js fiddle.
.test__container {
width: 800px;
}
.test__img {
width: 100%;
}
}
#container{
display:flex;}
<div id='container'>
<div class="test__container">
<img class="test__img" src='https://via.placeholder.com/350x150/' />
<h1 class="test__name">Davy Crocket</h1>
</div>
</div>
<br><br>
<div class="test__container">
<img class="test__img" src='https://via.placeholder.com/350x150/' />
<h1 class="test__name">Davy Crocket</h1>
</div>
Try this.
<html>
<head>
<style>
.page {
width: 500px;
}
.container {
float: left;
width: 50%;
}
img {
float: left;
width: 100%;
height: 500px;
object-fit: cover;
}
</style>
</head>
<body>
<div class="page">
<div class="container">
<img src="https://news.harvard.edu/wp-content/uploads/2022/02/20220225_wondering_dog-2048x1366.jpg" alt="" />
</div>
<div class="container">
<img src="https://www.princeton.edu/sites/default/files/styles/full_2x/public/images/2022/02/KOA_Nassau_2697x1517.jpg?itok=Hy5eTACi" alt="" />
</div>
</div>
</body>
</html>

Why the scroll bar is ignored on my div with overflow-x=scroll?

I have a div on my html that I want to apply a laterla scroll.
This is the html
<div class="section-container mt-5 row" >
<div class="section" v-for="(item,index) in board.sections" v-bind:key="index">
<div class="card-title">
<h5 class="text-center section-header">{{item.name}}</h5>
</div>
</div>
</div>
And this is the css im using:
.section-container{
overflow-x: scroll;
white-space: nowrap;
}
.section{
width: 30%;
margin-left: 2%;
margin-right: 2%;
}
I read in another post that this should do the trick with the lateral scrolling, but it is ignored, my divs just keep stacking on the same div. I'm applying it wrong? They should be aligned horizontaly and scroll through all of them.
Example here
I think you are using bootstrap. The bootstrap class row makes the element a flex-box with flex-wrap: wrap. This causes your element to wrap to the next row instead of flowing out of the container.
Add a rule in your section-container class to prevent flex-child wrapping.
.section-container {
overflow-x: scroll;
flex-wrap: no-wrap;
}
Also, you might need to set flex-basis or min-width on the children if you want them to have a minimum width.
I suggest you read more about flex-box. This can help you get started.

Horizontal scroll not working on a div element

#Here, I'm trying to create horizontal scrolling for a div element for my application. The div element consists of ul li element and some other div tags for my requirement. The Ul li elements are dynamically added inside the parent div element.
Although I could get the vertical scrolling working properly and my horizontal scrolling is displayed using overflow-x: scroll. I am not able to scroll it, the ul li elements gets distorted. I have set a predefined width of 700px for the div container also. Its like the horizontal scrolling is disabled. I am not using overflow anywhere else in the application
<div class="org-chart" appOrgachart [empArr]="employees" [orgaArr]="orgaArr" *ngIf="employees.length>0 && !isLoading">
<ul>
<li *ngFor="let emp of empArr">
<div class="user">
<div class="name">{{emp.empname}}</div>
<div class="role">{{emp.empdesgname}}</div>
</div>
</li>
</ul>
</div>
My CSS file:
.org-chart {
display: flex;
justify-content: center;
left: 29px;
position: relative;
overflow-x: scroll !important;
overflow-y: scroll;
height: 400px;
width: 65%;
transform: translateY(12%);
}
Looking at your code, providing overflow-x: scroll !important; is big no no from me, it should be the last option for you to use.
now coming to your requirement, you need to specifically provide overflow-x: scroll if you give overflow:auto it automatically gives you a scroll when needed.
now when is it??
when the height and width is more than the browser size that is when you will get the scrolling feature.
if you need a scroll within browser size then, decrease the width of the container and apply overflow:auto; that should give you a scroll on sight.
here is the example of what I am saying:
so what does it mean is when you want a scroll within the browser then you should have a child class and the width of that class should be less w.r.t the content so that it can overflow.
.org-chart {
display: flex;
justify-content: center;
left: 29px;
position: relative;
overflow: auto;
border: 1px solid black;
/*Main container */
height: 300px;
width: 65%;
}
.content {
width: 100%;
/* you should have another width inside main container */
border: 1px solid red;
}
<div class="org-chart" appOrgachart [empArr]="employees" [orgaArr]="orgaArr" *ngIf="employees.length>0 && !isLoading">
<ul>
<li *ngFor="let emp of empArr">
<div class="user">
<div class="name">{{emp.empname}}</div>
<div class="role">{{emp.empdesgname}}</div>
<div class="content">Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last
on only the last paragraph in the container, you can use :last child, see example below. Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it,
text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last on only the last paragraph in the container, you can use :last child, see example below. Notice that the text-align-last property sets the alignment
for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last on only the last paragraph in the container, you can
use :last child, see example below. Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH
of the paragraphs. To use text-align-last on only the last paragraph in the container, you can use :last child, see example below.</div>
</div>
</li>
</ul>
</div>
apply max-width property as 64% and overflow:auto

Force elements to always be inside a DIV

One thing I always seem to fight within web development is keeping things inside a div element. I often run into issues where I have a list of div wrappers with more divs and content within, and eventually, one of them bleeds out and causes a nightmare when it comes to styling. An example if I may.
If you inspect the element you'll notice the banner-content div doesn't wrap all of the content. The images and span elements are outside of it's reach, even so the icon-wrapper content does (once again) wrap around everything. I believe I know that the answer to that one (the img height is set to 100%).
It doesn't seem that big of a problem now, but when trying to align things with much more content and forms and responsive design, it gets kinda crazy. It almost feels like I'm adding some hacky code to make it all form nicely. Realistically it seems like everything stayed within my parent div sizes and elements, everything would behave as expected.
Is there a way to force divs to contain all the child node's within its reach?
.wrapper {
width:100%;
display:flex;
flex-direction:column;
}
.cool-banner {
display:flex;
height:60vh;
}
.banner-picture {
width:50%;
}
.banner-picture img {
object-fit: none;
object-position: center;
height: 100%;
width: 100%;
}
.banner-content {
display:flex;
flex-direction: column;
height:100%;
}
.icon-list {
display:flex;
}
.icon-wrapper {
display:flex;
flex-direction:column;
height:40vh;
}
.icon-wrapper img {
object-fit: contain;
object-position:center;
width:100%;
height:100%;
}
<div class="wrapper">
<div class="cool-banner">
<div class="banner-picture">
<img src="https://cdn.shopify.com/s/files/1/1150/2512/files/WG_Grill_ShootBeside_Oct2017-7_dd4f32ad-38ac-4a49-8a3c-332ba067835e_810x540.jpg?v=1553613536"/>
</div>
<div class="banner-content">
<h1>I'm Content</h1>
<div class="icon-list">
<div class="icon-wrapper">
<img src="https://cdn.shopify.com/s/files/1/1150/2512/t/41/assets/fire-silver.png?51152"/>
<span>Nice Fire</span>
</div>
<div class="icon-wrapper">
<img src="https://cdn.shopify.com/s/files/1/1150/2512/files/EPDA-Logo-small_x100-ConvertImage_small.png?v=1559164248"/>
<span>Nice Award</span>
</div>
</div>
</div>
</div>
If I'm understanding the question, there are a number of ways to constrain children so that they don't extend outside of their parent.
If you set overflow: hidden on the parent, children that are wider or taller than the parent will clip at the edges of the parent, though their width will remain the same.
You can set max-width: 100% on children to keep them from growing wider than the parent's width.
You can also set display: flex on the parent and min-width: 0 on the children to constrain children to the parent.
Things get a little dicier if you need to constrain heights, because children typically only respect their parent's height if the parent's height is explicitly set.
Sometimes you just cant fit your size 10 foot into a size 7 shoe.
That image takes up 50%, while not having enough real estate for the other column's content. Case in point - In your example, removing the flex-direction:column of .banner-content wraps all children as you may have intended

How to vertically center div relative to flexbox grandparent?

Given a div with display flexbox .wrapper (run and see snippet below) and a deeply nested div .text-container, how can I center the deeply nested div relative to the .wrapper and not relative to its parent .variable-height?
In the snippet below there are two columns with equal height and I want the text, which is placed in a variable height div inside each column, to be at the same level. I have set the display of the variable height div also to flexbox, so logically the text is centered, relative to it and not to the grandparent .wrapper, which is not what I want.
The only solution I came up with is to set position: relative; on .wrapper and on .text-container:
position: absolute;
top: 50%;
transform: translateY(-50%);
However, I am not sure, if it's a good idea to mix flexbox and absolute/relative positioning.
.wrapper {
background-color: white;
min-height: 200px;
width: 200px;
float: left;
margin-left: 50px;
display: flex;
flex-direction: column;
}
.wrapper .fixed-height {
background-color: orange;
min-height: 30px;
}
.wrapper .second {
background-color: yellow;
min-height: 30px;
}
.wrapper .variable-height {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.wrapper .variable-height .text-container {
width: 100%;
text-align: center;
}
<div class="wrapper">
<div class="fixed-height"></div>
<div class="fixed-height second"></div>
<div class="variable-height">
<div class="text-container">
<div class="title">Title</div>
<div class="subtitle">Subtitle</div>
</div>
</div>
<div class="fixed-height"></div>
</div>
<div class="wrapper">
<div class="fixed-height"></div>
<div class="variable-height">
<div class="text-container">
<div class="title">Title</div>
<div class="subtitle">Subtitle</div>
</div>
</div>
<div class="fixed-height"></div>
</div>
However, I am not sure, if it's a good idea to mix flexbox and absolute/relative positioning.
Well, it depends on what sort of behavior is acceptable to you.
When you absolutely position an element, you remove it from the document flow.
So, in this case, .wrapper and its flex items don't know that .text-container exists. If there's any flexibility to the container or items, they will overlap with .text-container. See this illustration:
Centering: Absolute Positioning vs Flexbox (re-size the window to see the difference)
Again, if the overlapping is acceptable to you, then absolute positioning is fine.
In terms of the flexbox specification, there's nothing wrong with mixing absolute / relative positioning with flex properties. The spec has a section on this subject:
4.1. Absolutely-Positioned Flex Children
An absolutely-positioned child of a flex container does not participate in flex layout. However, it does participate in the reordering step (see order), which has an effect in their painting order.
The static position of an absolutely-positioned child of a flex container is determined such that the child is positioned as if it were the sole flex item in the flex container, assuming both the child and the flex container were fixed-size boxes of their used size.
The effect of this is that if you set, for example, align-content: center; on an absolutely-positioned child of a flex container, the child’s static position will center it in the flex container’s cross axis.
Two things to note from the spec:
Although an absolutely positioned flex item is removed from the document flow (as expected), it still recognizes the order property.
You can still use flex properties to center an absolutely positioned flex item, but only under certain circumstances and only within the parent container, not the grandparent.