Is there a way to use the clearfix hack alongside flexbox? - css

I've been using flexbox for layouts, with CSS floats as a fallback for older browsers. On the whole this works well, since browsers that understand display: flex will ignore float on any flex items.
However, the one place that I've run into a problem with this approach is with clearfix. Clearfix is a widely-used hack that uses an invisible :after pseudo-element to make a container properly clear / contain any floated elements inside it. However, the problem is that this pseudo-element is treated as a flex item by browsers that support flexbox, which can lead to unexpected layout issues. For example, if you have two flex items and use justify-content: space-between, instead of being positioned at the start and end of the flex container, they will appear in the start and middle, with the invisible clearfix ::after pseudo-element taking the end position.
My question is: is there a way to use clearfix alongside a flexbox layout without causing these problems?

One way to handle this would be to consider alternative clearfix methods.
The ::after pseudo-element is one method but, as you noted, it becomes a flex item in a flex container. (See Box #81 in this answer for more details).
But there are various other ways to clear floats. For instance, you could use overflow: auto or overflow: hidden.
Check out some alternatives here:
What is a clearfix?
What methods of ‘clearfix’ can I use?
Clearing Floats: An Overview of Different clearfix Methods
Another way to solve your problem uses modernizr.com for feature detection.
From the website:
All web developers come up against differences between browsers and
devices. That’s largely due to different feature sets: the latest
versions of the popular browsers can do some awesome things which
older browsers can’t – but we still have to support the older ones.
Modernizr makes it easy to deliver tiered experiences: make use of the
latest and greatest features in browsers which support them, without
leaving less fortunate users high and dry.

Try this, it will deal with pseudo-elements in a flex container:
.clearfix::before,
.clearfix::after {
flex-basis: 0;
order: 1;
}

I'm not sure if this is the same issue you were having, but I was using a fairly complicated flex setup:
display: flex;
flex-wrap:wrap;
align-items: center;
I ran into a similar issue where I wanted to use clearfix to make sure I could split the content at a certain point, in my case it was to make some data break on specific screen sizes. I was absoutely stumped until I found a solution through trial and error that worked for me:
<div class="clearflex"></div>
.clearflex{
width:100%;
}
By adding an empty div with 100% width between flex content it seems to make that content break onto the new line exactly like clearfix did. You can also added a height to clearflex if you need some padding between the rows.

You can set flex-wrap to your flex container and width: 100% to after pseudo element so it will wrap and not mess with alignment.

One way to achieve that is to use overflow: hidden or overflow: auto on .clearfix & completely remove .clearfix::after.
.clearfix {
overflow: auto; /* or overflow: hidden; */
}
However, if you can't use overflow property on .clearfix for some reason, you can use margin-left: auto on the second div (considering your layout has only two column). That way the invisible ::after will be placed in between two layout divs.
.clearfix { ... }
.clearfix::after { .... }
.clearfix > div:last-of-type {
margin-left: auto;
/* for justify-content: space-between only.
* For other option, adjust accordingly */
}

Related

What is an alternative to css subgrid?

I'm working on a page with a pretty simple layout - basically a data table, but using grid layout so that the columns will adjust nicely depending on content size. I want to make the rows sortable (using jQuery), so I need to find a way to wrap all the cells of a same row in a container.
display: subgrid;
I've tried using subgrid but it seems it's not much supported at the moment.. Obviously, just nesting a grid doesn't work as it won't sync the column sizes between different grids..
Any idea on how to achieve that?
Here is my pen so far: https://codepen.io/anon/pen/PEjqgx
Depending on the context, display: contents may be a viable workaround for display: subgrid.
From caniuse: (bold mine)
display: contents causes an element's children to appear as if they
were direct children of the element's parent, ignoring the element
itself. This can be useful when a wrapper element should be ignored
when using CSS grid or similar layout techniques.
The big win here is that we can keep our current markup - which groups together each row of data - while keeping components of each row synced together because they are part of just one CSS grid - the grid container.
Regarding browser support: display: contents is supported by Chrome, Firefox and iOS 11.4+.
So getting back to the OP's sample Codepen, we can make use of display: contents to implement the desired result by:
1) Moving the grid container properties to the globalWrapper div and
#globalWrapper {
display: grid;
grid-template-columns: 1fr 1fr max-content;
grid-gap: 3px;
}
2) setting the rowWrapper divs with display: contents
.rowWrapper {
display: contents;
}
Updated Codepen demo
Using display:contents to simulate css subgrid is a hack: hacks add complexity — making the code harder to maintain and prone to other errors — and sooner or later they will stop working.
Beware of using display:contentsas a substitute for subgrid: there are good reasons why it should be avoided. Instead use either another Grid in the container element or Flex.
[Adendum 11/1/2020] Firefox supports Subgrid since V71, no word yet from the other browsers. There is a good explanations about the feature in codrops, and you can see some examples here. And this is the link to see the current support in all of the browsers in can I use
[Adendum 06/06/2022] Apple announces subgrid support for Safari 16

How to make IE 11 wrap flexbox items when the flex container is inside a floating element?

I'm trying to add a flexbox element to the content area of a two column layout. The layout has a fixed width sidebar and fluid content. It uses float: left and negative margins to achieve this.
The goal is for the flex container to be 100% width of the parent. Flex items should be displayed in rows, with excess items wrapping to the next row.
The straight-forward approach works fine in Firefox and Chrome:
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: stretch;
}
.flex-item {
flex: 1 0 100px;
padding: 10px;
border: 1px solid gray;
}
...
<div class="flex-container">
<div class="flex-item">Item</div>
<!-- more items here -->
<div class="flex-item">Item</div>
</div>
Full example (works in FF and Chrome, but not IE 11):
http://jsfiddle.net/btc9chw0/3/
The problem
In Internet Explorer 11, all items are displayed on a single row. They never wrap to the next row, even when there are lots of items. This causes the page to become much wider than the browser window.
After lots of experimentation, it appears that this is somehow related to the fact that the flex container is inside a float: left element. Removing the float allows items to wrap correctly, but breaks other parts of the layout. The content area can have other content in addition to the flexbox, and some of that content needs to use float: left and clear: both. Without a floating parent element, a clear: both would push everything below the sidebar. Giving .flex-container a fixed width also fixes the problem, but in this case we want it be 100% width.
Firefox screenshot:
IE 11 screenshot:
The question
Is there are way to make flex items wrap to the next row in IE 11 when the parent of the flexbox container has "float: left"?
Disclaimer: Please disregard, for the moment, the fact that this layout uses both floats and flexbox instead of just one or the other. In this case, flexbox is a nice-to-have enhancement for one part of the page, while the general layout must be more robust.
The underlying issue here actually has to do with the auto measurement of a container in a shrink-to-fit context. By making .content have a min-width of 100% you've left the max-width to auto so the browser needs to measure the content to know its max-width to shrink down around it.
In IE, complete layout will be done to get the exact result with no limitations if none were set (as is the case here, we actually have infinite space since we can scroll and you have limited the width anywhere within its ancestor tree). Webkit and Gecko had made some changes in the past to avoid having to actually do layout and do an approximation, even though the actual measurement results were incorrect since they didn't know how big other (shrink-to-fit containers were) they decided the perf benefits were worth the tradeoff. With Gecko, Webkit and Blink (due to forking from webkit) all using this same behavior we changed our implementation to match this in Microsoft Edge and so we render the same as Firefox, Chrome, Safari. To get the same result in IE11 you'll need to provide a maximum width constraint when in a shrink-to-fit context (floats, abspos, table cell, etc).
Ultimately I prefer the IE behavior because it actually makes sense and is consistent. If there is enough space to lay out the content, the layout shouldn't change (as is the case here). Here is a simpler example showing why this approximation can cause issues, there is still enough room in the viewport to render the same result in each case but because they can't determine the actual dimensions of the floated blocks you get different results in Chrome/Firefox/Safari/Edge; while in IE they produce the same consistent result.
Sorry for the long reply, but I wanted to provide the context for why IE seems incorrect here.
Let me know if you need any further clarification.

Are there any disadvantages to adding clearfix to all divs?

On a layout I'm working on (and in most cases otherwise), I can't think of any instances where I wouldn't want a div to not contain its floated children. So I'm thinking instead of adding a clearfix class to every element that needs it (mostly container divs), why not just make all divs already clearfixed like so:
div:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
Are there any disadvantages to this? I can't really see any while testing my current layout, but maybe some more knowledgeable people out there know better than I.
If you do this, then you will never be able to have multiple floated divs stack horizontally with one another, because your clearfixes are getting in the way.
So in a way, having a clearfix on every div element would nullify the effect of floating them, as well as related elements.
This is why articles often suggest applying clearfix to a certain class, then giving the desired elements that class instead:
.cf:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
In my opinion the clear fix is superfluous for most cases where it is used, it is far simpler just to use overflow: hidden.
Obviously if the element has dimensions set smaller than it's content, or you actually want the ability for a child element to sit outside it's parent, then this wont work. But eight times out of ten I find that overflow hidden wont cause any problems what-so-ever, and is much cleaner to implement.
With regards to setting the clear fix on every div, I would stay well away from this.
It would add quite a bit of extra processing to your page rendering.
It would be near-invisible to others working with your code.
Not to mention BoltClock's float problem.
I have however built layouts that have made copious use of overflow hidden with no ill effects.
It isn't a hack, it utilises in-built element rendering options.
If applied to each class that needs it, it is quite obvious to other developers.
It wont suffer the float problem.

Flexible div positioning

I have several divs on a page that all have the same width but different heights. They are all in one div, the #note1PreviewDiv. They all share the class .note, which has the following css code (among other):
.note{
width: 160px;
padding: 10px;
margin: 10px;
background: #e3f0ff;
float: left;
}
I thought with float: left; they would all automatically align so that they are well aligned among each other.
Here's a preview of what it looks like:
Current state http://posti.sh/img/ist.png
And here's what the positioning should be like:
Desired state http://posti.sh/img/soll.png
I think you get the idea. Somehow it seems to me the height of the leftmost div pushes the other divs in the second row to the right - but that's only guessing.
Thanks for your help!
Charles
You're not going to be able to do this easily with CSS only.
CSS3 has a new feature called column layout, but browser support is not great. IE9 and below don't support it.
See http://designshack.net/articles/css/masonry/ and the last example for CSS3 solution.
Have a look at these js / jQuery options for easier implementation and browser support:
masonry
isotope
vanilla masonry which doesn't need jQuery.
wookmark
The kind of lay out you want is really difficult (not possible?) without going for a column based approach and adding additional block elements to represent each column. This obviously won't work with a flexible number of columns if you want a dynamic layout based on screen size.
That said, you could always use JavaScript to dynamically place elements into columns, and get it to match the screen size.
Is the height of the parent container given a fixed value? If it is, try setting the height of the parent container to auto, and the overlow propery to hidden.

Help clearing floats, what do you think of this global method?

I'm just learning the ropes on clearing floats for all browsers and had and idea.
Do you see any harm in defining this globally for all div elements?
div {
_zoom: 1; /* Clear floats for ie6. Does NOT validate. */
overflow: hidden; /* Clear floats for all other browsers. */
}
There would probably only be a few special cases where the above two rules would need to be overwritten. Off the top of my head, I can't think of any problems that might come up as a result of the above rule, but maybe someone knows better?
What do you think?
EDIT 1:
Changed height: 100%; to _height: 1%;.
EDIT 2:
Changed _height: 1%; to _zoom: 1;.
This is the version I'm running with. Here is an excellent link to an article describing all clearing methods for newbies.
One potential problem you could run into is what happens when you float elements that arent divs. Your style covers <div /> tags, but nothing else so you'd have to keep that in mind in case you do use float on other tags.
It may be better to apply those styles to containers that need to clear floats rather than applying a catch-all that may not catch everything.
Also keep in mind that having hidden overflow may make it hard to apply some styles which rely on content extending beyond a div tag. A few situations I can think of are
styles for sides or corners of elements for adding shadows or rounded corners, which typically overflow their container.
Light boxes which may extend beyond the bounds of your container, if they're placed within a <div />
Custom javascript tooltips that are placed within <div />s. Tooltips typically "pop out" of their container, which could cause problems depending on how they're designed.
These issues are easier to work around if you only do it on elements you need to and not all elements.
It would cause problems. Take a look at these images, 1 is regular, 2 is with div {height: 100%;}
(source: zastica.com)
(source: zastica.com)
There were also a few other inconsistencies with just that one setting. So, you can get some strange unexpected behavior.

Resources