"br" is not friendly with the flexbox? - html

I got a table using flexbox and noticed one interesting feature: the br element can not do anything inside the flexbox.
Example:
.flexbox {
display: flex;
flex-wrap: wrap;
border: 2px solid red;
padding: 2px;
}
.item {
width: 50px;
height: 50px;
margin: 2px;
border: 2px solid blue;
}
.new-row, br {
display: block;
width: 100%;
height: 0px;
}
<p>Line break using div:</p>
<div class="flexbox">
<div class="item"></div>
<div class="item"></div>
<div class="new-row"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<p>Line break using br:</p>
<div class="flexbox">
<div class="item"></div>
<div class="item"></div>
<br>
<div class="item"></div>
<div class="item"></div>
</div>
In the example, div and br share the same properties, but div transfers elements to the new line, and br does not.
Why?

The implementation of the br element in CSS is very well known to be quite the mystery. Different browsers support a different set of properties on the element, to varying degrees of effect (although all of them do support setting display: none to remove it from the layout at least). CSS itself acknowledges this oddity as early as CSS1, having dedicated an entire subsection to it, and even now in CSS3 it's still severely underspecified.
This peculiarity involving flexbox is not new; it has been known since 2014. Basically, in current implementations br does not generate a principal box, but is instead treated as part of a contiguous run of text as described in section 4 of the Flexbox spec, generating an anonymous flex item that cannot be styled (because it's anonymous). This is similar to an orphaned display: table-cell element causing an anonymous table box to be created around it, except you can at least still style the display: table-cell element — in the case of the br element, the style properties you apply have no effect, and the anonymous flex item is laid out with the defaults.
In this case, since br itself is (mostly) empty and it is not being accompanied by any other bare text within the flex container, this results in an anonymous flex item with no dimensions, making it seem as though the br element has vanished completely.
Back in 2014 the CSSWG resolved this "mystery" not by changing the Flexbox spec, but simply to add a special definition for the br element to css-display-3 to account for the behavior seen here. But no such definition exists in the current version of that spec, nor the FPWD (which was published after the resolution!), nor the HTML spec, nor anywhere else. Nevertheless, the definition looks like this in terms of the current css-display-3 spec (which does not define any new properties, just changes the definition of display):
br {
content: '\A';
display: contents;
white-space: pre;
}
... which means that the br element doesn't generate a principal box, but simply an anonymous inline box containing a single newline.
Because this definition is still missing from css-display-3, I wouldn't immediately consider it canon just yet. Even so, the behavior seen here is extremely unlikely to change considering this is how the br element has been for so long.

One other option when using <br> in your code if you just have a single column of elements is to use flex-direction: column.
.flexbox {
display: flex;
flex-wrap: wrap;
border: 2px solid red;
padding: 2px;
flex-direction: column;
}
.item {
width: 50px;
height: 50px;
margin: 2px;
border: 2px solid blue;
}
<p>Line break using br:</p>
<div class="flexbox">
<div class="item"></div>
<br>
<div class="item"></div>
</div>

Unlike Chrome, you must add whitespace ( ) after a <br> in order for it to work in Firefox.
By doing so, you will have the same result in both browsers.
Conlusion:
Works only in Chrome: <br><br><br>
Works in both Chrome and Firefox: <br> <br> <br>

Related

Forbid flexbox items to flex w/o use of * selector

I work with BEM and use a flexbox container purely for alignment and responsive design purposes. The problem is that sometimes it also wants to scale its daughter elements, which I don't want. Like this:
.card {
width: 120px;
background: gray;
}
.container {
display: flex;
align-items: center;
}
.flex-item1 {
width: 50px;
background: blue;
}
.flex-item2 {
overflow-wrap: normal;
background: green;
}
.ruller {
width: 50px;
background: gray;
}
<div class='card'>
<div class='container'>
<div class='flex-item1'>
I'm picture 50px wide
</div>
<div class='flex-item2'>
I'm long text
</div>
</div>
</div>
<div class='ruller'>
My width is 50px
</div>
Here is the blue element is getting scaled and its rule width is ignored.
One direct solution for this is to just explicitly forbid flexing for every element.
.flex-item1 {
width: 50px;
background: blue;
flex: none; /* the fix */
}
But container is a general class, I'm using it in tens of different situations, I don't want to add more CSS code to all possible classes of its daughter elements, nor do I want to add another class like container-item to all those elements in HTML.
Another direct solution for this would be
.container * { /* the fix */
flex: none;
}
But this goes against general BEM guidelines on using selectors. I would like to avoid using * selector here.
Is there a way third way to do it? I.e. a way that doesn't add any CSS rules to styles of daughter elements and which does not use * selector.
What makes me ask such a question is the existence of rules like align-items, which are placed to the parent element (i.e. flexbox itself) by the acting on daughter elements (i.e. flex-box items). I imagine my solution would be is something like this:
.container {
display: flex;
align-items: center;
flex-items: none; /* a pseudo rule, which doesn't exist and need to be replaced by other rules to work */
}
If you insist on following BEM without exception, then you should have the rules you need within classes you've defined for your elements. That would be the BEM way. You may not like having that code in 20-30 different places as you say, but that is the tradeoff of BEM.
Personally I combine BEM with utility classes when it makes sense, I don't believe that following BEM blindly to the letter produces cleanest and easiest to maintain codebases.
On the other hand rise in popularity of Tailwind goes to say that BEM and similar methodologies don't work for all.
All this being said, I would suggest sprinkling some utility classes on your BEM project and enjoying best of both worlds.

Confusion between inline and block level elements in HTML/CSS while trying to display fractions [duplicate]

This question already has an answer here:
List of HTML5 elements that can be nested inside P element?
(1 answer)
Closed 1 year ago.
I have the following code on my page:
.fraction {
vertical-align: middle;
display: inline-block;
}
.frtop, .frbottom {
text-align: center;
}
.frbottom {
border-top: 1px solid;
}
<p style="text-indent: 2em;">
The fraction
<div class="fraction">
<div class="frtop">1</div>
<div class="frbottom">20000</div>
</div>
equals to 0.00005.
</p>
where I am trying to display an inline fraction in an indented paragraph.
However, the fraction is displayed on a separate line: There is a line break between the text The fraction and the fraction itself. How can I fix this?
Note 1: This problem does not occur if I use div instead of p to define my whole paragraph; however, in this case I have to add text-indent: 0; in the CSS code of the .fraction definition and the content does not seem semantically correct to me: I do want to use p to define all my paragraphs.
Note 2: Obviously, I have to replace div with span. However, I need some extra things in the CSS code I provided, so that it works.
Try this :
.fraction {
display: inline-flex;
flex-direction: column;
align-items: center;
text-indent: 0;
vertical-align: middle;
}
.frbottom {
border-top: 1px solid;
}
<p style="text-indent: 2em;">
The fraction
<span class="fraction">
<span>1</span>
<span class="frbottom">20000</span>
</span>
equals to 0.00005.
</p>
Considering the fraction is a part of the paragraph, it shouldn't be in a div anyway.
Edit:
The flex element allows you to display the content either as a row or a column. It's pretty useful for changing classic display.
Since .fraction is in flex, you need align-items to put the content in the middle.
For more information on flex, I would suggest this article: https://css-tricks.com/snippets/css/a-guide-to-flexbox/. This is a very good explanation; much better than everything I could write here :) .

NO CSS - html two divs side by side

Is there any possibility of creating two divs side by side in html without using css?
I could not find any solution and somehow believe, that this is not possible with pure html.
I have no chance to use css, therefore the only any solution with only html is required.
I think you misunderstand what it means to "do it without CSS". Remember that "CSS" effectively refers to the layout system used by every web-page in a modern web-browser (and by "modern" I mean: made since 2001).
So a web-page with no explicit style="" attributes, no <style> elements and no <link rel="stylesheet" /> elements is still using CSS: it still has the built-in user-agent stylesheet. If you use the now-obsolete presentational elements and attributes like <font> and border="" then those are converted into CSS rules by the browser. My point is that it's impossible to not use CSS.
...so I assume by "without CSS" you really mean "without an external stylesheet" or "without a separate <style> element", but in your comment reply you said that using <style> is acceptable, so I think you're confused about what your restrictions are:
Thank you for your reply Dai. Inline <style> works for me. How could it leads to solve the place two divs side by side? I do not want to do it without css, but i have to. It is all about to create an html file with plotly.js
Anyway, if you can use <style>, then just do something like this:
<style>
#parent {
display: flex;
}
#parent > div {
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 1;
}
#left {
border: 1px solid red;
}
#right {
border: 1px solid blue;
}
</style>
<div id="parent">
<div id="left">
</div>
<div id="right">
</div>
</div>
And if you cannot use <style> but you can use inline style="" attributes, then you can still do this:
<div id="parent" style="display: flex;">
<div id="left" style="flex-basis: 50%; flex-grow: 1; flex-shrink: 1; border: 1px solid red;">
</div>
<div id="right" style="flex-basis: 50%; flex-grow: 1; flex-shrink: 1; border: 1px solid blue;">
</div>
</div>
If you cannot add your own <style> elements nor style="" attributes then your only remaining option for laying out elements is by abusing <table> - but I won't post an example using <table> because I don't want to encourage others to do so - and because I've never encountered a system that allowed arbitrary elements but did not allow at least for custom style="" attributes.

When generating a PDF with puppeteer "break-inside: avoid" is ignored

I am generating a multi-page PDF from a webpage using puppeteer v 5.2.1.
I am using the following to ensure that this block element is not cut off at the page break:
.wrapper {
display: block;
float: left;
break-inside: avoid;
}
I have set up other paged media stuff using #page to see that Puppeteer can deal with paged media.
But my block elements still get cut off?
Pupetteer is emulating the screen. Though when it uses the default print emulation, I get the same results.
Is there something I am missing in my setup?
Ok, I have solved this issue.
The problem was that the container element for my .wrapper elements was an inline-block.
The wrappers themselves are block elements so they adhere to the break-inside CSS. However, if the surrounding container, which contains multiples of these .wrapper elements is an inline-block, then it is treated as a monolithic block by the pages media CSS, so the user agent will then choose to split this block at the end of the page - without respecting it's block children.
This is by design according to the specification:
https://www.w3.org/TR/css-break-3/#end-block
.parent {
display: block;
}
.wrapper {
display: block;
float: left;
break-inside: avoid;
}
<div class="parent">
<div class="wrapper">
<div>Some content</div>
</div>
<div class="wrapper">
<div>Some content</div>
</div>
<div class="wrapper">
<div>Some content</div>
</div>
</div>
In my original problem, my parent was wrongly declared as
.parent {
display: inline-block;
}
I think your question was already answered in this topic: https://stackoverflow.com/a/27754912/3681102
"This is a known problem. page-break properties apply only to block-level elements."
I have a similar issue with tbody groups inside tables not respecting page-break-inside: avoid;
For some reason, the CSS used on the parent didn't work for me.
But this worked:
.wrapper: {
float: left; width: 100%;
}
I am using Chromium 79, puppeteer 2.0.0 and chrome-aws-lambda 2.0.0 (I needed old versions).

Control order of vertically stacked elements using only CSS Flexbox

I'm trying to use the CSS Flexible Box Layout Module to control the order that elements are rendered. Here's some sample HTML (and fiddle):
<div id='outer-container'>
<div id='blue-objects' class='object-container'>
<p>In here we have a number of blue things.</p>
<p>The amount of content could be very small, or very large.</p>
</div>
<div id='green-objects' class='object-container'>
<p>This is very similar to the blue objects block, in that the amount of content is unknown at design-time, and it could be very small or very large.</p>
<p>It could be a complicated, nested set of child objects, although in this example there is nothing more than two <p> elements.</p>
</div>
</div>
/* Started with a columnar layout as given by the Flexplorer: http://bennettfeely.com/flexplorer/ */
.outer-container {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: column wrap;
flex-flow: column wrap;
}
.object-container {
-webkit-flex: 1 auto;
flex: 1 auto;
border: 1px dotted black;
padding: 0 10px;
margin: 10px;
}
#blue-objects {
order: 2;
font-weight: bold;
}
#green-objects {
order: 1;
font-style: italic;
}
My goal is to be able to use pure CSS to control the order the #blue-objects and #green-objects elements appear. All I've been able to accomplish so far is control the horizontal sort order.
The spec describes the order property as follows:
A flex container lays out its content in order-modified document
order, starting from the lowest numbered ordinal group and going up.
I would have thought this would mean that the #green-objects would appear before #blue-objects, because of the order values being 1 and 2, respectively... but it's not working in Chrome 36, Firefox 31, or IE 11.
According to caniuse.com, flexbox has good support in modern browsers. What am I doing wrong? How can I control the order of a vertically stacked set of elements using the CSS Flexible Box Layout module? Help with this fiddle would be greatly appreciated.
You should call #outer-container and not .outer-container in CSS file. Then the flex model will be triggered.
To only put blue objects last, then just apply: order:1; to it and nothing to others:
DEMO
Order defaut value is 0.