Use ellipsis until min-width, then wrap to next line - html

I would like to make a row consisting of three columns, where the left column is always on the left, and the right two columns are joined together (i.e. wrap together to the next line, if there is not enough space). This is easily achievable using flex and may look like this: https://jsfiddle.net/znxn9x1r/
The catch here is that I would also like the middle column (violet colored always-right/left) to be shrinkable up to some min-width using text-overflow: ellipsis. This means that when I start lowering the width of the page, the middle column should first start shrinking, and only after it is no longer possible, then the right two columns should wrap to the next line.
A mockup of what I want to achieve:
Then when the shrinking reaches the min-width of the middle column, it should wrap to the next line as before:
Now if there was no left yellow column and the whole row consisted only from the two right columns, I could use the answer from the following question: How to keep a flex item from overflowing due to its text?
This really behaves like it should, but only after the right group already wraps:
It does not shrink the middle column when it is still on the same line as the first yellow column:
^^ This should not happen, there is enough space for an ellipsis!
Here is my code, is it possible to achieve what I want with pure HTML/CSS?
* {
padding: 5px;
}
#container {
background-color: lightgreen;
display: flex;
flex-wrap: wrap;
}
#always-left {
background-color: yellow;
margin: auto;
margin-left: 0;
}
#right-group {
margin: auto;
margin-right: 0;
display: flex;
}
#shrinkable {
background-color: violet;
vertical-align: middle;
order: 1;
flex: 0 1 auto;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
#not-shrinkable {
background-color: lightblue;
vertical-align: middle;
order: 2;
flex: 1 0 auto;
}
<div id="container">
<div id="always-left">
always-left
</div>
<div id="right-group">
<div id="shrinkable">
always-right / left
</div>
<div id="not-shrinkable">
always-right / right
</div>
</div>
</div>
https://jsfiddle.net/mnmyw245/

One method that may work for you involves disabling flex-wrap: wrap on the flex container.
#container {
background-color: lightgreen;
display: flex;
/* flex-wrap: wrap; <-- REMOVE THIS */
}
This forces everything to stay on the same line.
Then, when you feel it's okay for wrapping to begin, restore wrap with a media query.
This takes wrap control away from the browser and puts it in your hands.
Here's an example:
#media ( max-width: 200px ) {
#container { flex-wrap: wrap; }
}
revised fiddle

Related

Container does not shrink when inner text wraps

I am trying to have two elements horizontally aligned where the one on the left has text that may wrap then sizing the screen, and the one on the right allows for no wrapping. When the content wraps, the first element maintains the width of content + (wrapped word - pixels causing wrapping), instead of shrinking to fit the content.
I created an example on Fiddle where you can see the grey background of the first element having no content for a couple of pixels, instead of resizing to only include the text.
.container {
display: flex;
width: 760px;
}
.item {
background-color: grey;
width: fit-content;
block-size: fit-content;
}
.item2 {
background-color: green;
white-space: nowrap;
align-self: flex-start;
}
<div class="container">
<div class="item"><span> This Text to auto-adjust to only fit the content when wrapping</span></div>
<div class="item2">This should be right next to last word on first line on the left</div>
</div>
JSFiddle Demo
Is there a way of achieving an auto-size to only fit-content on resizing of the screen so the 2 element stays as close to the text of the first one as possible?
Elements inside a flexbox has flex-grow and flex-shrink set by default, which allows them to bypass the basic width and height properties.
To solve this problem, just disable flex-grow and flex-shrink:
.item {
background-color: grey;
width: fit-content;
block-size: fit-content;
flex-grow: 0;
flex-shrink: 0;
}

How to fix the css to keep 4 cards in a row while they are center aligned?

Facing an issue with a css property (Flex) . I have multiple cards and i want it to be 4 cards per row so that irrespective for screen size it will always have 4 cards per row. Since i am using display element as Flex it adjusted according to screen size. Very new to this front end dev work, can you please check and fix my CSS property to align 4 cards in a row.
here is the code:
https://codesandbox.io/s/tender-feynman-we6n9s?file=/src/productsConfig.js
Basically here i want 4 cards per row.
You can add flex-basis, it sets the size of the content box, so your css flex-basis: 25% on class .react-card-flip
Update
if you don't want increase your space then try this:
.react-card-flip:nth-child(3n+1):not(:first-child) {
break-after: always;
}
this code just simply found your 4th element and add a break on it. Just try to decrease your page using ctrl + scroll your mouse to see. It max 4 cards per row.
try on sandbox
Using flex, and since you want the width of the cards to be fixed (300px), and assuming you're only working on large screens, to guarantee displaying 4 elements of 300ps in a row, it's best to also set the width of the parent to 1500px for example, in this case only 4 elements with margins, paddings will be displayed in a single row.
.container {
display: flex;
flex-wrap: wrap;
width: 1500px;
justify-content: center;
margin: auto;
}
.react-card-flip {
flex: 1 0 300px;
border: 1px solid red;
margin: 5px;
min-height: 50px;
}
<div class="container">
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
<div class="react-card-flip"></div>
</div>
Try with adding this style to your style.css file for responsive auto card wrap on space.
.container {
display: flex;
flex-wrap: wrap;
}
.card {
width: calc(25% - 40px);
margin: 20px;
}
I thought the problem is "incorrect level".
Press "f12" in https://we6n9s.csb.app/, then you will see the 1st level is "container".
The 2nd level is "react-card-flip".
The 3rd level is "react-card-flipper".
The 4th level is "react-card-front".
The 5th level is "card".
Maybe you could use .react-card-flip but not .card
.react-card-flip {
position: flex;
flex: 1 0 22%;
border: 1px solid red;
width: 22%;
height: 300px;
min-height: 50px;
}

Align divs to start at the same vertical line with varying widths

I am sure there is an easy way to solve this, but I'm at my wits end:
I have the following layout:
With the following simple CSS:
.row {
width: 100%;
display: flex;
align-items: center;
margin: 15px 0px 0px;
}
.label {
flex: 0.5;
}
.field {
flex: 1;
}
However, I want the fields next to Label 2 through 4 to look like this:
How can I achieve this? I want a maximum width of around 100px. If it set max-width: 100px; I get this:
Which I guess is from the flex: 0.5; I gave the label. I could obviously set the margin-left of the field to negative-something, but that stops working when I resize the window.
Thank you!
I think you need to define the flex-basis of your label-element, in a responsive unit like %, as you intent to always have a "hard" left edge.
Like so:
flex: 0 0 20%;
Codepen example

display: table row does not allow scroll

I am currently designing a book website and on the right-hand side want to have a "Table of contents" which is in a fixed position and scrollable. I set the header for my website to "display: table-row" and similarly did so with the table of contents and its internal elements. (A header and a the scrollable list of chapters) As I understand it, display: table row should make a div element fill the remaining height and only the remaining height. [1] However, in this case, the content continues offscreen instead of allowing the user to scroll through it. (You can see the problem on this jsfiddle: https://jsfiddle.net/chrmon2/9wzjckvn/6/)
My css:
#container {
height: 300px;
border: 1px solid black;
}
#header {
background: blue;
display: table-row;
}
#toc h1 {
background: red;
display: table-row;
}
#toc #content {
background: yellow;
overflow-y: scroll;
display: table-row;
}
Is this not a capability of display: table-row or am I doing something wrong? Thanks
https://www.whitebyte.info/programming/css/how-to-make-a-div-take-the-remaining-height
As I understand it, the effect you want is as follows:
When there is remaining space, stretch the table of contents items;
When the space is too small, begin scrolling.
This is an ideal application of CSS Flexboxes. Flexboxes allow you to define how items stretch (or don't), how they align with each other, how they wrap etc.
In this case, we're going to use flexboxes for all the divs in this example.
.container, .toc, .content {
display: flex; /* begins flexbox layout */
flex-direction: column; /* Flexboxes can be aligned from left-to-right
or from top-to-bottom. In this case, we want
them to be top-to-bottom. */
flex-grow: 1; /* On .container, this does nothing. However, for
children of Flexboxes, this tells them to grow
if any space is still available. */
min-height: 0; /* For a more complicated reason, this is necessary
to make flexboxes scroll correctly. This needs
to be set on all the flexboxes in this example. */
}
.toc .content .item {
flex-grow: 1; /* Make items grow when there is room available */
}
.content {
overflow-y: scroll;
}
You can see the effects of this at this JSFiddle.
Just remove display: table-row from #toc #content and add this :
#content{
max-height:200px;
}
height can be as per your requirement.

Using flexbox, vertically center items and respect top 150px space of flexbox container

I am trying to craft a flexbox in CSS with the following characteristics:
Three items stacked and centered within the middle of the flexbox
One item locked to bottom of the flexbox
Flexbox is set to a size of 100vh and 100vw, taking up visible screen area
Items within flexbox must not occupy the top 150px of the flexbox. This may push some items below the viewable area (see "Desired Result 3" in image below)
Ideally, a pure CSS solution is feasible with the HTML elements provided
The Problem
The vertically centered boxes won't honor the 150px space I would like to put at the top of the flexbox, and I haven't been able to create an elegant way to make sure the items don't float up past the top of the screen if I make the window too short. That is, the example in "Desired Result 3" in the image above remains elusive.
Example Code
HTML:
body {margin:0; font-family: sans-serif; font-weight:bold;}
.parentFlexBox {
background-color:grey;
display: flex;
flex-direction: column;
margin-top:0;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
height:100vh;
width:100vw;
}
.itemA, .itemB, .itemC, .itemD { padding:5px; text-align:center; margin-bottom:5px; color:#fff;}
.itemA { background-color:red; width:50px; margin-top:auto;}
.itemB { background-color:hotpink; width:150px; height:50px}
.itemC { background-color:purple; width:40px; height: 35px}
.itemD { background-color:blue; margin-top:auto; width: 80px;}
<div class="parentFlexBox">
<div class="itemA">A</div>
<div class="itemB">B</div>
<div class="itemC">C</div>
<div class="itemD">D</div>
</div>
Please run above code in full screen to see the issue
This might work for you:
HTML (add two invisible flex items)
<div class="parentFlexBox">
<div class="itemA">A</div>
<div class="itemB">B</div>
<div class="itemC">C</div>
<div class="itemD">D</div>
<div class="itemE">E</div><!-- invisible spacer item with 150px height -->
<div class="itemF">F</div><!-- invisible spacer item with 120px height -->
</div>
CSS
.parentFlexBox { justify-content: space-between; } /* changed from `center` */
.itemA { order: 1; } /* removed `margin-top: auto` */
.itemB { order: 2; }
.itemC { order: 3; }
.itemD { order: 5; height: 30px; } /* added `height` for centering calculation;
removed `margin-top:auto` */
.itemE {
order: -1;
flex: 0 0 150px; /* don't grow, don't shrink, remain at 150px height */
visibility: hidden;
margin-bottom: auto; /* stick to top of container */
}
.itemF {
order: 4;
flex: 0 1 120px; /* don't grow, shrink proportionally, start at 120px height */
visibility: hidden;
margin-top: auto; /* go south as much as possible (sticks to Item D) */
}
/* NOTE: Item D has height 30px. Item F has height 120px. Together they equal height of
Item E. Equally balanced on both ends, Items A, B & C are centered in the container. */
DEMO 1
I placed the spacer divs last in the mark-up to keep with the alphabetical ordering. If you prefer to list all divs (including spacers) in order, that would eliminate the need for the order property.
Also, in the demo, the code includes borders, in case you want to see the spacers at work. Just disable the visibility property.
Update (based on comment)
Nice, a couple of questions though: 1) Possible to make it so that BCD don't change height when resizing the window? 2) Possible to make the gray background extend to contain D when window is short? 3) Possible to do items E and F as pseudocode elements?
Question #1: Yes. Add flex: 0 0 <<absolute height>> to BCD. For instance, add flex: 0 0 50px to each item, which tells them to stay fixed at 50px height. (Also, remove the height property from each rule, to avoid any potential conflict with flex.)
Question #2: Yes. Instead of limiting the container to height: 100vh, use min-height: 100vh.
Question #3: Yes. Remove the E and F code from the HTML and CSS, and add this to the CSS:
.parentFlexBox::before {
content: '';
flex: 0 0 150px;
visibility: hidden;
margin-bottom: auto;
}
.parentFlexBox::after {
content: '';
flex: 0 1 100px;
visibility: hidden;
margin-top: auto;
order: 4;
}
DEMO 2