Set same height as other divs, without javascript, and inside flexbox - css

I am trying to achieve this:
I set a max-width to my paragraph, and I want the two images to have the same height as the paragraph. But the problem is I have a complex flexbox design, as shown below.
Red and green boxes are divs with display: flex property, and blue boxes are content. I made this schema to make the whole thing responsive for small landscape screens (sorry my 2nd drawing looks like it's on mobile).
Large screens:
Small screens:
So here is what I have right now, with height: 100% on the images:
Is there a way to do this in pure CSS? I tried javascript but there are conflicts between flexbox and JS, which lead to this: video of how my JS/CSS conflict looks like
Thanks!
body {
min-height: 100vh;
position: relative;
justify-content: center;
align-items: center;
padding: 1em;
background-color: cornsilk;
}
#row1 {
display: inline-flex;
justify-content: center;
align-items: center;
}
#row1 #row1_col1 {
display: inline-flex;
}
#row1 #row1_col1 #photo {
margin-right: 2em;
margin-right: 2em;
}
#row1 #row1_col1 p {
background-color: coral;
height: fit-content;
width: fit content;
text-align: justify;
width: 31em;
margin-right: 0px;
margin-left: 0px;
}
#row1 #map {
margin-left: 2em;
}
<div id="row1">
<div id="row1_col1">
<img src="http://via.placeholder.com/400x400" id="photo" class="about_imgs">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing. <br> <br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Uot enim ad minim veniam, quis nostrud. <br> <br>
xcepteur sint occaecat cupidatat non proiden.
</p>
</div>
<img src="http://via.placeholder.com/1053x526" id="map" class="about_imgs">
</div>

There are several ways to do this, first of all, you should make both of used align-items property have flex-start attribute just like this: align-items: flex-start; as I did in the below snippet to make sure all your items begin from the same place (keep in mind this is optional and for making sure all your items will begin from the same certain point in the UI, and if you don't want to do this you can skip this), the second thing you must consider is the p tag does the default margin from top and bottom so to override it with margin: 0; in the p tag itself. The last and important thing at all you should define a fixed height for your p tag also, and make sure your photos wouldn't pass a certain point with the max-height property, so you have to add this property to both of your images. You can see the results below:
body {
min-height: 100vh;
position: relative;
justify-content: center;
align-items: center;
padding: 1em;
background-color: cornsilk;
}
#row1 {
display: inline-flex;
justify-content: center;
align-items: flex-start;
}
#row1 #row1_col1 {
display: inline-flex;
justify-content: center;
align-items: flex-start;
max-height: 100px;
}
#row1 #row1_col1 #photo {
max-height: 200px;
margin-right: 2em;
}
#row1 #row1_col1 p {
background-color: coral;
height: fit-content;
width: fit content;
text-align: justify;
width: 31em;
height: 200px;
margin: 0;
}
#row1 #map {
max-height: 200px;
margin-left: 2em;
}
<div id="row1">
<div id="row1_col1">
<img src="http://via.placeholder.com/400x400" id="photo" class="about_imgs">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing. <br> <br> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Uot enim ad minim veniam, quis nostrud. <br> <br> xcepteur
sint occaecat cupidatat non proiden.
</p>
</div>
<img src="http://via.placeholder.com/1053x526" id="map" class="about_imgs">
</div>
NOTE: I just used 200px for the fixed height for more illustration it could be whatever you want to.

Related

how to make a heading always stay horizontal inplace of overflow

I am working on a portfolio project and I am creating the projects section.
The width of the projects section is around 350px so only some of the title could be visible but if the text is not able to fit in 350 px it is making the text overflow vertically but I want it to overflow horizontally.
here is my HTML&CSS:
.project-container {
display: grid;
height: 350px;
width: 350px;
background: #c4c4c4;
margin-bottom: 3%;
}
.project-title{
height: 45px;
width: 100%;
background-color: red;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
overflow: auto;
}
<div class="project-container">
<h1 class="project-title">Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores dignissimos praesentium dolorem saepe velit at libero a consectetur atque molestias.</h1>
</div>
and here is my result when the text can't fit in 350px:
but I want the overflow to be horizontal
white-space: nowrap;
I think you just want this?
.project-container {
display: grid;
height: 350px;
width: 350px;
background: #c4c4c4;
margin-bottom: 3%;
}
.project-title{
height: 45px;
width: 100%;
background-color: red;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
overflow: auto;
white-space: nowrap;
}
<div class="project-container">
<h1 class="project-title">Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores dignissimos praesentium dolorem saepe velit at libero a consectetur atque molestias.</h1>
</div>
You've given your .project-title a width which automatically means the text inside will wrap at the end of the line. If you want it to overflow horizontally instead of vertically, you need to:
Allow space for it to overflow.
Prevent it from wrapping.
This can be achieved by changing .project-title[width] to .project-title[min-width] (meaning the space is at least the width of the container, but may be larger) and setting .project-title[white-space]=nowrap (meaning text is not allowed to break across lines).
.project-container {
display: grid;
height: 350px;
width: 350px;
background: #c4c4c4;
margin-bottom: 3%;
}
.project-title{
height: 45px;
min-width: 100%;
white-space: nowrap;
background-color: red;
margin: 0;
display: flex;
overflow: auto;
}
<div class="project-container">
<h1 class="project-title">Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores dignissimos praesentium dolorem saepe velit at libero a consectetur atque molestias.</h1>
</div>
just add white-space: nowrap; to class project-title

“white-space: nowrap;” destroys flexbox layout: Why?

This is my code:
* {
font-size: 40px;
font-family: Arial;
color: blue;
text-transform: uppercase;
}
div {
height: 100vh;
}
#one {
display: flex;
width: 100%;
}
#two,
#four {
width: 45px;
background-color: blue;
}
#three {
width: 100%;
display: flex;
}
#button,
#text {
border: 1px solid blue;
margin: 10px;
}
#text {
width: 100%;
/* overflow: auto;
white-space: nowrap; */
}
<div id="one">
<div id="two">
</div>
<div id="three">
<div id="text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
<div id="button">Button</div>
</div>
<div id="four">
</div>
</div>
I want to add white-space: nowrap; for the text (#text), but it destroys the layout, the areas with the blue backgrounds get lost. I saw that adding min-width: 0; or min-height: 0; could help, but it doesn't work in this case.
Has somebody an idea to fix that? Would be very thankful. :)
For clarifying: The text from #text should stay in one line, that's all.
What is happening?
The divs two, three and four are had the flex property set to its default values:
div {
flex-grow: 0;
flex-shrink: 1;
flex-base: auto
}
Which means that for each div should: calculate the "best" width (flex-base: auto), if there is enough space for the three divs there is no need to grow to fill it (flex-grow: 0), if there isn't enough space shrink them proportionally (flex-shrink: 1).
When you put white-space: nowrap; in the three div, there is not enough space (since it "best" width will be as much as is needed to hold the single long line of text.
Solution:
Add flex-shrink: 0 to the blue divs, and flex-grow: 1 and overflow: auto to the central div. This way, the blue divs will always have 45px width, and the central one will always fill the remaining space.
UPDATE
Since you now have a new div and button inside div three, there is a few additional changes: We'll make div three also a flex container, and set flex-grow and flex-shrink to appropriate values for the inner text and button.
* {
font-size: 40px;
font-family: Arial;
color: blue;
text-transform: uppercase;
}
div {
height: 100px; /* You'll probably want a lower height */
}
#one {
display: flex;
width: 100%;
}
#two,
#four {
flex-shrink: 0; /* no shrink */
width: 45px;
background-color: blue;
}
#three {
display: flex;
flex-grow: 1; /* fill all available space */
width: 0px; /* will grow from 0px to fill all space*/
}
#text {
flex-grow: 1; /* fill all available space */
border: 1px solid blue;
margin: 10px;
white-space: nowrap; /* moved from "#three" */
overflow: auto; /* moved from "#three" */
}
#button {
flex-shrink: 0; /* no shrink */
border: 1px solid blue;
margin: 10px;
}
<div id="one">
<div id="two">
</div>
<div id="three">
<div id="text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
<div id="button">Button</div>
</div>
<div id="four">
</div>
</div>
According to MDN, setting white-space: nowrap "suppresses line breaks (text wrapping) within the source." This means that all of your line breaks will be gone for that element and it will go on horizontally as long as there is text.
But to keep everything within the viewport and keep the blue bars around the text, you should first wrap your Lorem Ipsum text in a p tag or other text element, and then change your CSS to something like this:
:root {
--bar_width: 45px;
}
* {
font-size: 40px;
font-family: Arial;
color: blue;
text-transform: uppercase;
}
div {
height: 100vh;
}
#one {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100vw;
}
#two,
#four {
width: var(--bar_width);
background-color: blue;
}
#three p {
max-width: calc(95vw - (2 * var(--bar_width)));
white-space: nowrap;
overflow: scroll;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
<title>Document</title>
</head>
<body>
<div id="one">
<div id="two">
</div>
<div id="three">
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
</div>
<div id="four">
</div>
</div>
</body>
</html>
This adds an overflow property set to scroll so that the text can be reached without it streching out the viewport. I also set the max width the element can take up so that CSS knows when to start cutting off the text. I also added flex-direction: row; justify-content: space-between; to your #one selector so that the elements space out horizontally.
You can now change the max-width property set in the #three p selector to any value you want and the text (with scroll) will be centered between the blue bars.
You need to set the flex-basis property of div#three, div#two, and div#four to something like 33.3%
https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis
You're also setting the height of all divs to 100vh, and when the overflow occurs on your inner block elements, it doesn't know where to stop unless you truncate the text: https://css-tricks.com/flexbox-truncated-text/
* {
font-size: 40px;
font-family: Arial;
color: blue;
text-transform: uppercase;
}
#one {
display: flex;
width: 100%;
}
#two,
#four {
flex-basis: 33%;
width: 45px;
background-color: blue;
}
#three {
width: 100%;
flex-basis: 33%;
white-space: nowrap;
overflow-x: hidden;
/* white-space: nowrap; */
}
<div id="one">
<div id="two">
</div>
<div id="three">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<div id="four">
</div>
</div>

Flexbox - image on the right side

I have an image on the right side item of a flex container. As you can see in the codepen, there is a gap when expanding the screen (caused by the max-width on the image, which is unavoidable).
However I'm just wanting to move that image to the extreme right-side, so the gap isn't as noticeable.
This needs to be friendly with IE11, and the image needs to be responsive. I would like to avoid using a float on the image if possible (would've thought there is a cleaner way of achieving this using flexbox)?
HTML:
<div class="container">
<div class="image">
<img src="http://www.stevensegallery.com/1000/1400">
</div>
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus aliquid eius quia expedita illo sequi optio labore assumenda.
</div>
</div>
CSS:
.container {
background-color: red;
display: flex;
flex-direction: row-reverse;
}
.container > .image {
flex: 1 0 0%;
}
.image > img {
display: block;
max-width: 100%;
max-height: 300px;
}
.container > .text {
flex: 2 0 0%;
}
Codepen:
https://codepen.io/neilem/pen/zjpXKZ
You could use vertical-align instead display, then text-align:
.container {
background-color: red;
display: flex;
flex-direction: row-reverse;
}
.container > .image {
flex: 1 0 0%;
text-align:right;/* and here*/
}
.image > img {
vertical-align:top;/* here */
max-width: 100%;
max-height: 300px;
}
.container > .text {
flex: 2 0 0%;
/* and eventually */
margin:auto 0;
}
<div class="container">
<div class="image">
<img src="http://www.stevensegallery.com/1000/1400">
</div>
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus aliquid eius quia expedita illo sequi optio labore assumenda.
</div>
</div>
Use justify-content property on container and remove flex properties form the flex-child. Your code will look like this. Hope the result is what you desired.
.container {
background-color: red;
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
.image > img {
display: block;
max-width: 100%;
max-height: 300px;
}

Positioning divs inside wrapper, one of them must have y-scrollbar when content overflows

I'm trying to accomplish the following layout, but I'm having trouble with the description box height definition. I'm trying to avoid javascript.
Right now I have both the wrapper and the title bar working as they should, the title and description divs being nested inside the wrapper div:
#wrapper{
position: fixed;
right: 0;
width: calc(100vw - 1.51 * 95vh - 5vh);
top: calc(40px + 2.5vh + 2.5vh);
height: calc(100vh - 40px - 40px);
}
#title{
width: 100%;
height: auto;
top: calc(2.5vh + 40px + 2.5vh + 5vh);
}
What about the description div? Can anyone point me in the right direction?
Thanks!
Flexbox can do that.
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
header {
background: lightblue;
}
.content {
flex: 1;
overflow-y: auto;
background: orange;
}
.spacer {
height: 2000px;
/* for demo purposes */
}
<div class="container">
<header>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quos tenetur magnam labore laboriosam dolores, fugit ipsum quibusdam, aperiam totam itaque soluta debitis cumque provident repudiandae.</header>
<div class="content">
<div class="spacer"></div>
</div>
</div>

How to truncate long text with ellipsis but always show icon after ellipsis

What I'm trying to accomplish is a title which fills its available parent div width, but if its copy doesn't fit in the div it should truncate with ellipsis. Additionally it should also have an icon after it, which shouldn't disappear on truncation, but always show after the ellipsis.
Another requirement is that the parent div should have one or more buttons, of not-specific width, that stay on the far right, but if the div is resized it should truncate the long title, allowing the icon to show next to the ellipsis as I described before.
Visually, my desired result looks like this:
Up until now I've achieved the following:
/* Helper styles not relevant to the example */
/* Simple flag object from #csswizardry */
.flag {
display: table;
width: 100%;
}
.flag .flag__section {
display: table-cell;
vertical-align: middle;
}
/* Right float text from bootstrap */
.text-right {
text-align: right !important;
}
/* Colors for better visibility */
.container {
background-color: #55606d;
color: #333;
padding: 20px;
}
.flag__section--a {
background-color: #22d398;
}
.flag__section--b {
background-color: #91c1f8;
}
.fluid-text__icon {
background-color: #fecb52;
}
/* Styles relevant to the example */
.container {
max-width: 700px;
}
.fluid-text {
text-align: left;
}
.fluid-text__inner {
max-width: 100%;
}
.fluid-text__inner,
.fluid-text__copy {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fluid-text__copy,
.fluid-text__icon {
float: left;
}
.fluid-text__copy {
padding-right: 5px;
}
.fluid-text__icon {
margin-top: 30px;
}
/* I'd like to not set explicit max width here */
.title {
max-width: 600px;
}
<div class='container'>
<div class='flag'>
<div class='flag__section flag__section--a fluid-text'>
<div class='fluid-text__inner'>
<h1 class='fluid-text__copy title'>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque earum in, voluptas dolorum sit ab modi facere tempora est, sequi molestiae! Commodi vitae sapiente ipsum, nisi facilis impedit aut? Repellendus!
</h1>
<span class='fluid-text__icon'>icon</span>
</div>
</div>
<div class='flag__section flag__section--b text-right'>
<button>ACTION</button>
</div>
</div>
</div>
However, my only concern is that I have to explicitly set .title max-width which is not scalable and I would like to avoid it.
Is there any way to do it without js?
Flexbox can solve this, we just have to expend the ellipsis to the .description div and make a few minor tweaks.
* {
box-sizing: border-box;
}
.parent {
width: 80%;
margin: auto;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1em;
padding: .5em;
border: 1px solid grey;
}
.description {
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
}
.text {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
flex: 0 0 auto;
background-color: rebeccapurple;
color: white;
padding: .5em;
margin: 0 .25em;
}
.button {
flex: 0 0 auto;
background-color: #ccc;
padding: .5em;
}
<div class="parent">
<div class="description">
<span class="text">Lorem sit amet, consectetur adipisicing elit doloremque earum in, voluptas dolorum sit ab modi facere tempora est, sequi molestiae! Commodi vitae sapiente ipsum, nisi facilis impedit aut? Repellendus!</span>
<span class="icon">I</span>
<span class="icon">I</span>
<span class="icon">I</span>
<span class="icon">I</span>
</div>
<div class="button">
Button
</div>
</div>
<div class="parent">
<div class="description">
<span class="text">Lorem sit amet</span>
<span class="icon">I</span>
<span class="icon">I</span>
</div>
<div class="button">
Button
</div>
</div>
The following uses flex and relies on the known width of the button which seems like the use-case here. The whole contained can have dynamic size, of course. The icon can be any size, too.
.parent {
width: 400px;
background-color: yellow;
display: flex;
justify-content: space-between;
}
.description {
width: calc(100% - 50px);
display: flex;
}
.text {
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
display: inline-block;
background-color: tomato;
}
.button {
width: 50px;
background-color: blue;
}
<div class="parent">
<div class="description">
<span class="text">Lorem sit amet, consectetur adipisicing elit doloremque earum in, voluptas dolorum sit ab modi facere tempora est, sequi molestiae! Commodi vitae sapiente ipsum, nisi facilis impedit aut? Repellendus!</span>
<span class="icon">ICON</span>
</div>
<div class="button">
Button
</div>
</div>
<div class="parent">
<div class="description">
<span class="text">Lorem sit amet</span>
<span class="icon">ICON</span>
</div>
<div class="button">
Button
</div>
</div>

Resources