Flexbox layout wider than browser [duplicate] - css

This question already has answers here:
CSS: Width in percentage and Borders
(5 answers)
Closed 2 years ago.
expected output: A horizontal line, and the word "testing" below, with no horizontal scrollbar.
actual output: A horizontal line with the word "testing" below, but there a horizontal scrollbar, which can be used to move roughly 5px, regardless of browser width.
This is the minimum code required to reproduce the problem:
body {
margin: auto;
display: flex;
flex-direction: column;
}
hr {
min-width: 100%;
}
<html>
<body>
<section>
<hr>
<span>
testing.
</span>
</section>
</body>
</html>
As you can see with "run snippet", you can scroll to the right and make the "t" in testing partially off the page.
Questions:
Why? How do I make a flexbox layout that uses only the width of the browser? I thought that adding body { width: 100vw;} would help, but it doesn't appear to change anything.
How can I debug this behavior without asking SO for help? If I take away any of the CSS lines, the problem disappears, but so does the formatting I desire, so I can't say which of them is at fault. How could I figure out what the problem is on my own?

First of all: your flex layout is working fine! The issue lies within the <hr> element, which sneakily takes up some horizontal space. It has borders on both sides – 1px each.
Here are three different solutions, take your pick!
Get rid of the borders
hr {
min-width: 100%;
border-left: none;
border-right: none;
}
Subtract the border widths from the total
hr {
min-width: calc(100% - 2px);
}
Change the element's box-sizing
hr {
box-sizing: border-box;
min-width: 100%;
}

Related

Grow to fit available space, then eagerly wrap text instead of expanding parent [duplicate]

This question already has answers here:
How to match width of text to width of dynamically sized image/title?
(2 answers)
Closed 6 months ago.
Consider the example below, a tooltip or modal or something outside the normal layout flow where the container is able to grow, but should shrink to fit its contents. Here I would like the header (blue) to fit on a single line, (greedily) expanding the parent. That is, to behave like it normally would. But the "body text" (red) should only grow to fill the available space and then (eagerly) wrap the text.
Unfortunately there seems to be no obvious CSS property to express eagerly wrapping text layout.
article {
position: absolute;
background: whitesmoke;
padding: 1em 2em;
}
header {
color: blue;
}
main {
color: red;
}
<article>
<header>This should expand parent to fit.</header>
<main>This should use available space, but wrap instead of expanding parent.</main>
</article>
PS: This might just be my search or problem description skills being terrible, but I've not found anything even describing this problem, let alone the solution. Please link anything you can find that is related to this.
One trick I stumbled upon is to set min-width: 100% and then set max-width to the actual minimum value.
min-width: 100%;
max-width: min-content; /* or even 0 */
You might think that setting max-width: 100% as well would work. Nope! I'm guessing because 100% then would refer to the width after its "preferred" width has been applied.
I would love a proper explanation of why this works, but my understanding of it is simply that max-width overrides the internal "preferred" width, and then min-width overrides max-width. Seeing as this is CSS, I'm sure it's much more complicated though :)
article {
position: absolute;
background: whitesmoke;
padding: 1em 2em;
}
header {
color: blue;
}
main {
color: red;
min-width: 100%;
max-width: min-content;
}
<article>
<header>This should expand parent to fit.</header>
<main>This should use available space, but wrap instead of expanding parent.</main>
</article>

For a CSS flexbox, allow an element to shrink to minimum(its intrinsic width, an absolute length) [duplicate]

This question already has answers here:
Flexbox children shrink up to a certain point (but don't expand if they don't need to)
(3 answers)
Closed 2 years ago.
I have a box that displays a number of text elements, one after the other along a row. I do not want the text within each element to wrap. Instead if there is insufficient room then it should truncate the text and show an ellipse.
This is easy to obtain using display: flex, and allowing each element to shrink to zero.
But the smaller elements are shrunk so much that the text almost completely disappears. In that case I would rather shrink the smaller elements a little less, and shrink the bigger elements more. This can also be obtained by giving each element a bigger min-width (say 100px) so that it cannot shrink beyond a certain point.
My problem occurs when one of the text element's intrinsic width is already smaller than 100px. Since I just specified that the element had a longer min width, the browser leaves extra space after the element. I don't want that extra space.
I would prefer not to use java-script. I'm seeking a solution using CSS. It's so close that I feel that it should be possible, but none of my attempts have come out correctly.
If I knew in advance which text elements were tiny, then I can specify that the tiny elements should not flex at all, and get the desired outcome. But without using javascript I do not know which elements are tiny.
If I could set the min-width of an element to the minimum of its intrinsic width and 100px then I would get the desired outcome. Although CSS does have a min() function which may be used for min-width, unfortunately it appears that I am not allowed to use max-content as an argument to that function.
The description of min-width on MDN (https://developer.mozilla.org/en-US/docs/Web/CSS/min-width) states that fit-content(100px) is a syntactically valid way of specifying the min-width. I hoped to craft an element whose minimal content size is zero, and max size is the text element's intrinsic length. Then fit-content(100px) would either be 100px, or if that's larger than the intrinsic length, the intrinsic length. But whenever I use fit-content() with an argument the browser says that the expression is invalid.
Finally I tried to use a grid display. But then fit-content() either uses the intrinsic width or 100px, but does not expand further. I tried experimenting with minmax with no luck (it seems I cannot put fit-content() as an argument to minmax()). Besides I do not know the number of text elements, but a grid display wants me to specify that number so I don't think a grid can be made to work.
So is there any way to obtain the desired outcome using just CSS. Since this text is for an Electron program, I only care about Chrome as a browser. I have an example below showing each of my attempts.
main {
display: flex;
flex-direction: column;
width: 600px;
border-style: solid;
border-color: black;
border-width: 1px;
}
span {
background-color: skyblue;
padding: 10px;
margin: 0 10px 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 0 1 auto;
}
section {
width: 100%;
display: flex;
}
.set-min-width span {
min-width: 100px;
}
.set-min-width .no-shrink {
flex: none;
min-width: initial;
}
.use-max-expression span {
min-width: min(100px, max-content);
}
.use-fit-content div {
flex: 0 1 auto;
min-width: fit-content(100px);
display: flex;
}
.use-fit-content div span {
min-width: 0;
}
.use-grid {
display: grid;
grid-template-columns: fit-content(100px) fit-content(100px) fit-content(100px);
}
.use-grid span {
min-width: 0;
}
<main>
<h4>The hidden overflow allows each text item to shrink to nothing<br> Both small and medium elements are heavily truncated<br></h4>
<section>
<span>Medium length</span>
<span>Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
<h4>By setting a min-width to 100px I can control truncation of medium element. But the tiny element now has extra space after it that I do not want.</h4>
<section class="set-min-width">
<span>Medium length</span>
<span>Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
<h4>1: This is what I want.<br> But to obtain it I had to specify a different style for the tiny element so that it would not flex. But I don't know in advance which elements are tiny.</h4>
<section class="set-min-width">
<span>Medium length</span>
<span class="no-shrink">Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
<h4>2: I want the min-width to be the element's max-content if this is smaller than the truncation limit<br> `min(100px, max-content)` would return the correct result, but it is not valid CSS and so is ignored</h4>
<section class="use-max-expression">
<span>Medium length</span>
<span>Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
<h4>3: I tried to use fit-content(arg)<br> The inner element has min-width 0, so its min-content size should be 0<br> Its max-content size is the intrinsic width of the text<br> So the fit-content(100px) size should be 100px if that's smaller than intrinsic
width, or the intrinsic width otherwise.<br> Despite MDN stating that fit-content with argument is valid CSS for min-width, the browser rejects `fit-content(100px)`</h4>
<section class="use-fit-content">
<div><span>Medium length</span></div>
<div><span>Tiny</span></div>
<div><span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span></div>
</section>
<h4>4: Using fit-content(100px) in a grid does not work either. The elements are indeed not expanded if natural width is smaller than 100px. But the elements do not flex to take rest of space.<br> Besides a grid won't work because the number of columns is
not known in advance.
</h4>
<section class="use-grid">
<span>Medium length</span>
<span>Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
</main>
I was giving this a little play around and this was the best I could come up width. The problem that I can see is that flex-box is terrible for not obeying boxes without setting its inner elements with a max-width of some kind. There is a few other answers I found on Stackoverflow but none of them seem to really fix what you are asking for. In my answer I used max-width on the spans, along with text-overflow: ellipsis and overflow: hidden to create something close to what you had requested.
code below and codepen - here https://codepen.io/rl4444/pen/oNLQVRr?editors=1100
HTML
<main>
<h4>my solution</h4>
<section class="box-items">
<span>Medium length</span>
<span>Tiny</span>
<span>Longer text that has to be truncated to fit within the section. It is far far far far too big to fit.</span>
</section>
</main>
CSS
main {
max-width: 600px;
width: 100%;
border-style: solid;
border-color: black;
border-width: 1px;
position: relative;
box-sizing: border-box;
}
span {
background-color: skyblue;
padding: 10px;
margin: 0 10px 10px 0;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 300px;
}
section {
display: flex;
box-sizing: border-box;
max-width: 100%;
}
.box-items span {
border: 1px solid red;
overflow: hidden;
}

How to force the padding-right to be respected in a CSS grid item when it overflows? [duplicate]

This question already has answers here:
Last margin / padding collapsing in flexbox / grid layout
(4 answers)
Closed 5 years ago.
I'm trying to get a centered dialog-like content with minimal markup and CSS and I almost got it working with the following code (you can try it in CodePen here: https://codepen.io/rosenfeld/pen/Rxgwrq):
#container {
display: grid;
padding: 1em;
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
background-color: white;
align-content: center;
justify-content: center;
}
#item {
text-align: justify;
font-size: 20px;
text-shadow: 1px 1px lightblue;
max-width: 400px;
background-color: lightyellow;
padding: 1em;
overflow: auto;
}
h1 { text-align: center; color: darkred; }
a { color: darkred}
<html>
<head>
<title>404 - Not Found</title>
</head>
<body>
<div id=container >
<div id=item>
<h1>404</h1>
Sorry, the page you are looking for does not exist. You may want to navigate to our main page. If you just clicked on a broken link, please get in touch so we can fix it.
</div>
</div>
</body>
</html>
The only issue I found was that the right padding of the item is not respected when the content overflows. Try shrinking the window width as much to force the horizontal scroll bar to appear and you'll notice that the item padding-right is completely ignored.
Is it possible to fix this without changing the markup or using :before and :after pseudo-selectors in the CSS?
P.S.: My first attempt to implement this was using Flexbox but I found several issues that don't seem to happen with grid layouts. For example, with Flexbox I was forced to use "margin: auto" for the item instead of the alignment properties, as they would make the top content disappear. Another difference is that with grid layout the bottom padding is respected, the only issue being the right padding (Update: in Chrome, but not in Firefox, for example, so this is not consistent among browsers). Using CSS grids allowed me to get closer to what I want with less and cleaner code when compared to using Flexbox. Also, the problem with using "margin: auto" is that you're unable to actually set up some margin to the item.
This is because the word can not be broken by a line break. And if it does not fit, part of it is on the "territory" of padding.
For exam give to .item property word-break: break-all;.

Chrome 100% width and 100 vw overflow [duplicate]

This question already has answers here:
How to remove the space between inline/inline-block elements?
(41 answers)
Closed 5 years ago.
Here's a repro.
Padding off, margins off, I don't see what's causing the space circled below. I'm using normalize, it doesn't matter. I get that the vertical scroll bar changes things, but shouldn't 100% width fix this?
The screenshot is using canvas width, max-width 80% and the right hand is allowed to size by the browser. If I set to 20% it wraps below.
Update: For those too lazy to click the repro link, here's a similar snippet:
.model-div {
background: black;
display: inline-block;
height: 100vh;
max-width: 80%;
width: 80%;
}
.ui-console {
display: inline-block;
height: 100vh;
max-width: 20%;
width: 20%;
}
<body>
<div class="model-div"></div>
<div class="ui-console">
<button class="reset" onclick="model.fReset()">Reset</button>
<button class="blind-mode" onclick="model.fToggleBlind()">Toggle Blind Mode</button>
<div class="log-text-div"></div>
</div>
</body>
Browsers detect ANY amount of whitespace as 1 space, therefore it prints a space between the two items, thus causing the second item to fall. (Unless you use a workaround.)
Possible solutions:
1.Eliminate your whitespace inside your HTML. The easiest way to do this is to use something to minify your HTML, which honestly is a good practice anyway.
2.Set the font-size of your parent to zero
Parent (body, in your example.)
.parent{
font-size:0;
}
Children
.parent>*{
font-size:16px;
}
3.Float the children (Bootstrap does this in v3, before it switched to flexbox.)
.model-div,.ui-console{
float:left;
}

Centered CSS pages that are longer than one screen appear 5px~ further to the left than shorter ones - how do I stop this?

This problem has been perplexing me for a while now, and I've tried researching it but so far I've just turned up sites that tell me how to center things but that's not the problem. The problem is that while #content looks like it's centered, when the page takes up more than one screen it causes the #content to appear about 5px to the left of where it appears when it is less than one screen in height. Is there a way to fix this without forcing my shorter pages to reach the bottom screen or beyond?
Here's how I'm centering my content:
body {
margin: 0;
padding: 0;
}
#content {
width: 800px;
margin: 0 auto;
overflow: hidden;
padding: 0;
}
I'll admit that there's a couple more divs in there, but I don't that's really relevant to this problem...
#asc99c is right.
The scroll bar is causing your problem.
When it appears, it pushes everything over.
To solve this (if you must), you could make your pages taller than 100%. Something like
body, html{
height:100%;
}
div{
height:101%;
}
With div being your main content div.
Example: http://jsfiddle.net/jasongennaro/7NYnS/
The following CSS will force the vertical sidebar to appear, even on pages that are shorter than the viewport height. This will prevent the horizontal shift that you're noticing.
html {
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
Via http://egilhansen.com/2007/03/28/css-trick-always-show-scrollbars/

Resources