I'm using a grid layout consisting of two div elements with the following column template:
fit-content(25%) auto.
I want to have the first div as high as the grid height with a vertically written and centered text in it.
I also want the first div to contain a fieldset, thus I set display: flex and align-items: stretch on the fieldset so the contained items have the maximum available height.
I set up the following example:
div#grid {
display: grid;
grid-template-columns: fit-content(25%) auto;
}
div#first-column > fieldset {
display: flex;
align-items: stretch;
height: 100%;
box-sizing: border-box;
}
div#sideways {
writing-mode: tb-rl;
transform: rotate(0.5turn);
text-align: center;
}
<div id="grid">
<div id="first-column">
<fieldset>
<div id="sideways">
Sideway Text
</div>
</fieldset>
</div>
<div id="second-column">
text<br/>
to<br/>
make<br/>
the<br/>
grid<br/>
higher<br/>
<br/>
<br/>
</div>
</div>
As you can see, the vertical text in the first grid column is out of bounds.
When re-enabling the text-align: center property in firefox using the css debugger the text gets rendered correctly.
In chrome the layout changes when re-enabling the box-sizing property.
See the following video:
https://screens.totally.rip/2018/09/vokoscreen-2018-09-25_23-33-02.webm
My guess is that the browser fails to calculate the width of the first grid column because the text is written vertically.
But maybe I'm just not using some css properties correctly.
If you want the first-column to take up the all width ..try
flex:1;
In the first-Column div.
But if you want the .first-column
To be on the left side as in asidebar
Set the grid-area and define each then apply to the divs
.grid {display:grid;
grid-template-column: ...
grid'template-row:....
grid-area:
"first first second"
"first first second"}
.first-column {grid-area:first}
.Second-column:{grid-area:second}
that is : if you wanted two vertical columns , first bigger than second column
notice :have used class (.)but don't mind am typing using ma phone , so it kinda sucks just use your number sign
I reported the bug and it turns out that this is already known. Apparently the child fails to report the correct width because of the orthogonal flow.
See my bug report and the underlying issue.
I haven't been able to find a chromium issue for this behavior, but I guess the bug is also already known there.
Note that the firefox and chromium bugs are actually not the same.
The minimal test case I provided with my bug report renders fine in chromium, but the example from my question above doesn't. I guess it has something to do with the flex layout.
Related
Is it possible to apply styles once an item wraps?
I have a 2 column flexbox where the first item sticks to the left and the one on the right should be in the center of the remaining space. The solution is to add margin: auto to the second item.
// Not relevant for the question - toggle container width
document.querySelector('button').addEventListener('click', () => {
const flexbox = document.querySelector('#flexbox');
if (flexbox.style.maxWidth) {
flexbox.style.maxWidth = null;
} else {
flexbox.style.maxWidth = '300px';
}
});
#flexbox {
display: flex;
flex-wrap: wrap;
gap: 20px;
border: 2px solid #397298;
}
#flexbox>div {
background: #8bc6e3;
padding: 20px;
}
#item2 {
margin: auto;
}
<div id="flexbox">
<div id="item1">Flex item 1 with quite some content</div>
<div id="item2">Flex item 2</div>
</div>
<button style="margin-top: 30px">Toggle shrink container</button>
Now the question is, how can I remove the margin: auto of #item2 if it's wrapped?
I want it to be on the left side and not centred.
This is what I want:
Not wrapped:
Wrapped:
There were multiple other instances where I wanted to change the style of the flexbox items when they wrap.
I find it very hard sometimes to write general CSS rules on more complex responsive designs. Did a lot of fiddling with grid as well, but it seems that there is no option to customize the wrapped items, even though it changes the page layout and item arrangement quite a lot.
I'm looking forward to container queries that go in this direction, but it's not yet supported by all browsers.
Edit: the button is not question relevant
The items wrap because of a narrow screen size, not because a user makes an action that could be caught by JS.
If you want to do this with pure css, you only choice is to use mediaqueries afaik. Usually you want to wrap the items when the app is used on phone or some other small device. You can also control the behavior in a more deterministic manner if you give the flex-items a basic width, so you are sure when they'll wrap and when not.
Let's say you want to have 2 rows of some fixed size content:
then you can give both
flex: 0 0 50%
This will make the flex-basis 50% of the parents width.
now with a media control the wrapped state
#media(max-width 600px) { margin: none; }
I guess there is no way to achieve this without js in the first place, quoting a stackoverflow fellow from this post:
In CSS, once the browser renders the page on the initial cascade, it
doesn't reflow the document when an element wraps. As a result, parent
elements don't know when their children wrap.
A JSFiddle of it: http://jsfiddle.net/24tL8mkq/3/
I want the red highlighting to continue all the way across the box.
Right now, it's set-up such that:
<div style='width: 500px; overflow: auto; border: 1px solid black; padding-top:-5px;'>
<pre id='pre_1'>
<!-- code box -->
</pre>
</div>
with the relevant css (this is the CSS that I want to extend across the entire div, through the overflow) being:
.bad {
background-color: palevioletred;
width: 100%;
}
I get that I can't use width: 100% as that'll only extend to the right most side of the overflow always, but I can't set a static width as I don't know what the size of the box could be.
I'd really prefer to keep this a HTML/CSS solution if possible just to make this as portable as possible.
Interesting problem. The following works for me in the latest Firefox, Chrome and IE11, though I'd consider this somewhat "experimental" - definitely should be further tested if you need to support a broader range of browsers.
http://jsfiddle.net/24tL8mkq/5/
pre {
display: table;
}
pre > div { display: flex; }
I wish I could tell you why this works, but I don't know. I wasn't able to find another combination that works, however. My guess: setting the pre to display: table makes it so the width will go wider than 100% (500px), as tables will do (when their children are wider than the table). Setting flex on the div children is filling the available space since all the children should be equal width.
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
Closed 5 months ago.
I'm playing with flexbox system in CSS and I can't figure out how to solve my problem.
If I have box with long text, which breaks to two lines, box grows to full width available and I don't want that. If text is on many lines then I want box to grow to width of the longest line. Well, my english is not so good that's why I have images to better show what I want to achieve.
This is what I have now:
And this is what I want to have:
I looked for ready solution in google (and stackoverflow) but without luck.
I prepared also JSFiddle for that: http://jsfiddle.net/f98VN/4/
Is it possible to do what I want and if yes then how can I achieve that? If not, what are your suggestions?
Code:
HTML
<div class="flex-parent">
<div class="item1"></div>
<div class="item2">text is here</div>
<div class="item1"></div>
</div>
CSS
.flex-parent {
display: flex;
justify-content: center;
width: 550px; /* it has width of the whole page, in fiddle I changed it to fixed */
align-items: center;
}
.item1 {
background: red;
height: 100px; /* it has constant width */
width: 100px;
}
.item2 { /* it's width is fluid, depends on text inside which is modified by JS */
background: pink;
font-size: 100px;
}
You may shrink middle container to the longest word using :display:table;width:1%; DEMO or use inline-block and inline-table, dropping the flexmodel : DEMO (this is it)
To keep words together you may use a non breaking character in between words you want to keep aside on same line : DEMO
Edit:
Above demos works in some browsers. In Chrome and Opera content moves to the side of the page.
Fixed version: http://codepen.io/gc-nomade/pen/izKFG
Well, the extra space appears because the whitespace break is a fake effect applied by the browser. What in fact happens, and it's hidden by the browser, is that the word is breaking between its letters, then the extra-space is actually the space that the letters really take.
You can see it by setting the text div to word-break: break-all; http://jsfiddle.net/f98VN/10/
It's not the effect you asked, but at least it doesn't leave extra space.
I got it to appear the way you want using percentages not fixed pixel width,
changed width: 550px; to width:70%;
check out this Updated fiddle
I've been given a design to create in HTML/CSS that I think may be impossible, but I want to be absolutely sure before I admit defeat and go with a compromise.
A number of items containing variable length text are arranged into sets of two such that they form columns where the columns are distributed across the available width exactly, but ensuring each column is no wider than its widest item. Thereby it uses horizontal space as efficiently as possible while still ensuring items align perfectly as a grid. Consider this example -
[-a--] [-cccccc-] [-eee-] [-g---]
[-bb-] [-dddd---] [-ff--] [-hhh-]
Perhaps this looks tabular, but consider that the items must also wrap when the container shrinks, and still the columns maintain their magical alignment -
[-a---] [-cccccc-]
[-bb--] [-dddd---]
[-eee-] [-g------]
[-ff--] [-hhh----]
I can't work out how to resolve the recursive dependency of widths. That is that the width of each "column" is defined by the longest item in that column, but the total available width is known and must be an exact sum of the columns widths.
I'm happy to use a CSS3 only solution, falling back to a fixed item width solution for older browsers, but I am completely stumped as to what CSS properties can achieve this magic.
Just to provide some kind of starting point, here's a Codepen using CSS3 columns: http://codepen.io/anon/pen/kiGgp
It's no good as the columns are distributed evenly, and I'm wondering if there's a way to distribute them optimally instead.
I didn't manage to achieve what you specified even after numerous tries with the FlexBox model. (BTW: this model is currently poorly supported by browsers)
But, in my efforts, I came with a decent solution, maybe you'll like it too.
Demo in this Fiddle
I've manage to evenly distribute the space between the elements in each row, while allowing element wrapping.
each element get the exact amount of space he needs, and the rest is divided as spaces within the row.
but, this width remain even when elements wrap. so you don't have the 'Column like' display.
this is pure CSS, and cross Browser.
Tested on: IE10, IE9, IE8, Chrome, FF
HTML
<div class="wrap">
<div class="pair">
<p>a</p>
<p>b</p>
</div>
<div class="pair">
<p>cccccccc</p>
<p>dddddd</p>
</div>
<div class="pair">
<p>ee</p>
<p>f</p>
</div>
<div class="pair">
<p>ggggggggggg</p>
<p>hhhhhhhhh</p>
</div>
<div class="pair">
<p>iiii</p>
<p>jjjjjj</p>
</div>
<div class="filler"></div>
</div>
CSS
*
{
padding: 0;
margin: 0;
}
.wrap
{
background-color: #ccc;
line-height: 0;
text-align: justify;
}
.pair
{
line-height: normal;
background-color: #ddd;
display: inline-block;
width: auto;
}
.filler
{
width: 100%;
height: 0;
font-size: 0;
display: inline-block;
vertical-align: top;
}
In working on a layout, I decided to try combining a float-based layout for the major columns with a table-based layout for the sub-elements. Thus, my html/css markup was along these lines:
HTML:
<div class="column">
<div class="sub-element"></div>
<div class="sub-element"></div>
</div>
<div class="column">
<div class="sub-element"></div>
<div class="sub-element"></div>
</div>
...
CSS:
.column {
float: left;
display: table;
width: 15%;
margin: 2%;
/* ... */
}
.sub-element {
display: table-cell;
/* ... */
}
The specific widths and margins aren't critical. See this jsFiddle for a reference example.
What I saw happening was that each column block, going left to right across the page, had slightly smaller margins than the last. Since no additional markup or CSS was present to make this happen, I was confused. After playing around with different values, I discovered that commenting out display: table caused the normal behavior I was expecting, e.g. constant column widths.
Now, I can use alternative methods to get the layout I want, that's not a problem; but I am really curious why this is happening. Any thoughts?
EDIT
It looks like this is a webkit bug. display: table with float and margins works fine in Firefox. Any suggestions on a fix for webkit for posterity?
Further EDIT
I just tested in Safari and it seems to work there as well. WTF Chrome??
Final EDIT
After testing in Firefox 18, Safari, and Chrome Canary (in addition to standard Chrome), it appears that this is in fact a Chrome-specific bug.
The easiest fix is to add a simple additional wrapper div inside each of the ones being floated to contain the content and set the wrappers' CSS to width: 100%; height:100%; display: table;, then remove the display: table from the outer elements being floated. Works like a charm.
http://jsfiddle.net/XMXuc/8/
HTML:
<div class="column">
<div class="sub-element-wrapper">
<div class="sub-element"></div>
<div class="sub-element"></div>
</div>
</div>
<div class="column">
<div class="sub-element-wrapper">
<div class="sub-element"></div>
<div class="sub-element"></div>
</div>
</div>
...
CSS:
.column {
float: left;
width: 15%;
margin: 2%;
/* ... */
}
.sub-element-wrapper {
width: 100%;
height: 100%;
display: table;
}
.sub-element {
display: table-cell;
/* ... */
}
This should not happen. Horizontal margins on block-level tables should be calculated in the same way as with any other block-level non-replaced elements, as described in section 10.3.3 of the CSS2.1 spec, regardless of which table layout algorithm is used. In particular, percentages values for margins should be calculated based on the width of the containing block of the element that you're displaying as a table; since all your elements are siblings that share the same parent and the same margin percentage value, they should be equidistant as long as they are floating block boxes.
In all browsers except Google Chrome, the elements are equidistant, as expected. So my best guess is that this is another Chrome bug.
If you comment out the display: table declaration — which as you say causes the behavior to return to normal — browsers will still generate anonymous block table boxes within your floats to contain the table cells. This should not adversely affect the layout, but if it does, I can't comment further as I'm not intimately familiar with how table layout works in terms of CSS.