CSS scrolling of container with dynamically sized children - html

I have a container which is populated dynamically with child elements. The width attribute for individual child elements is retrieved from backend in % adding up to 100%. This is because the desired effect is that the childs preserve size proportions in comparison to one another.
.wrapper {
display: flex;
width: 100%;
}
.item {
overflow: hidden;
height: 20px;
}
<div class="wrapper">
<div class="item" style="width: 30%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 15%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 5%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 40%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 10%">Lorem ipsum dolor sit amet</div>
</div>
The problem is that there can be an arbitrary number of children and the more of them the more squashed they become. Consequently stopping to fit the content.
Therefore I would like them to have a min-width and be able to scroll the container horizontally while still preserving the proportions retrieved from the database.
I tried:
Setting width on the container to a fixed value e.g. 2000px and overflow-x to auto. The width could be calculated somehow on rendering the page. It makes the childs scale nicely to add up to cover the 100% of the width of the container. The issue is that the scrolling doesn't work, because the container is physically 2000px wide and you have to scroll the whole page rather than the container
Setting min-width on childs causes the proportions to be lost
So I need a solution that combines both of them but can't seem to figure it out. I would appreciate any help and ideas.

You can use flex-wrap: wrap on the .wrapper so that when the children cannot fit the width of the parent they will simply go to another row. This way they can easily fit horizontally, but they will stretch vertically instead.
.wrapper {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.item {
overflow: hidden;
height: 20px;
}
<div class="wrapper">
<div class="item" style="width: 30%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 15%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 5%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 40%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 10%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 30%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 15%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 5%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 40%">Lorem ipsum dolor sit amet</div>
<div class="item" style="width: 10%">Lorem ipsum dolor sit amet</div>
</div>

I managed to solve the problem thanks to #Michael_B's answer to this question.
I changed my html to:
<div class="wrapper">
<div class="item" style="flex: 0 0 30%">Lorem ipsum dolor sit amet</div>
<div class="item" style="flex: 0 0 15%">Lorem ipsum dolor sit amet</div>
<div class="item" style="flex: 0 0 5%">Lorem ipsum dolor sit amet</div>
<div class="item" style="flex: 0 0 40%">Lorem ipsum dolor sit amet</div>
<div class="item" style="flex: 0 0 10%">Lorem ipsum dolor sit amet</div>
</div>
and CSS to:
.wrapper {
display: flex;
width: 100%;
overflow-x: auto;
justify-content: flex-start;
}
Note that there was an issue with the content overflowing on the left side, so you couldn't scroll to it. This is what justify-content was needed for. I found the solution here.

Related

CSS on hover display hidden div not working

HTML:
<div class="top-container">
<div class="primary-text">lorem</div>
<div class="secondary-text">lorem</div>
</div>
<div class="secondary-container">
<h2>Lorem ipsum dolor sit amet.</h2>
</div>
<div class="info-container">
<div class="container-one">
<div class="box1">1</div>
<h3>lorem</h3>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing.</p>
</div>
<div class="container-two">
<div class="box2">2</div>
<h3>lorem</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing.</p>
</div>
<div class="container-three">
<div class="box">3</div>
<h3>lorem</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing.</p>
</div>
</div>
<div class="info-sec">
<img src="test.png" alt="blah">
<p>Lorem ipsum dolor sit amet.</p>
</div>
Relavent CSS:
.info-sec{
visibility:hidden;
}
.box:hover + .info-sec{
visibility:visible;
}
If I change the hover from the box to the info-container it works fine:
.info-container:hover + .info-sec{
visibility:visible;
}
But hovering using box does not work. I've also tried using display: none; and display: block;
Codepen: https://codepen.io/colton-22/pen/jOwoMxL
The + is adjacent Sibling Selector. So when you use:
.info-container:hover + .info-sec{
visibility:visible;
}
It works because info-sec is the first next sibling of info-container. But when you use:
.box:hover + .info-sec{
visibility:visible;
}
It doesn't work because info-sec is not the sibling of info-container.
According to my knowledge, there is no selector in css which works for you. So, you have to use javascript to achieve this.

Flex: make child with same height of absolute sibling

I must create a section with two half divs with the same height, but the first must inside the container and other outside, like that sketch:
I have searched other solutions but I couldn't get them to work, like flex:1, align-stretch, probably because of the way I did it. Maybe you can fresh my mind, by suggesting another way.
Here is my code:
.bg-cyan {
background-color: cyan;
}
img {
max-width: 100%;
}
.right-half {
right: 0;
left: 50%;
border: 2px solid purple;
}
.container {
border: 2px solid red;
}
.col-6 {
flex: 1;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.1/css/bootstrap.min.css" integrity="sha384-VCmXjywReHh4PwowAiWNagnWcLhlEJLA5buUprzK8rxFgeH0kww/aWY76TfkUoSX" crossorigin="anonymous">
<section class="position-relative bg-cyan">
<div class="container position-static p-0">
<div class="row align-items-stretch">
<div class="col-6">
<h4 class="text-secondary mb-6">This col must be the same height of sibling absolute -></h4>
<h3>Staying inside the container</h3>
<ul>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
</ul>
</div>
<div class="col-6 position-absolute right-half p-0">
This is absolute positioned because the layout require the image to go outside of container until the page end, with no height setted because of responsive and dynamism.
<img src="https://picsum.photos/956/870">
</div>
</div>
</div>
</section>
I think you don't have to make the right side to absolute, just use the flexbox feature itself. Try this:
.bg-cyan {
background-color: cyan;
}
img {
max-width: 100%;
}
.right-half {
right: 0;
left: 50%;
border: 2px solid purple;
}
.container {
display: 'flex';
border: 2px solid red;
flex-direction: 'row';
}
.col-6 {
flex: 1;
align-self: 'auto';
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.1/css/bootstrap.min.css" integrity="sha384-VCmXjywReHh4PwowAiWNagnWcLhlEJLA5buUprzK8rxFgeH0kww/aWY76TfkUoSX" crossorigin="anonymous">
<section class="position-relative bg-cyan">
<div class="container position-static p-0">
<div class="row align-items-stretch">
<div class="col-6">
<h4 class="text-secondary mb-6">This col must be the same height of sibling absolute -></h4>
<h3>Staying inside the container</h3>
<ul>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
<li>Lorem ipsum dolor sit ame;</li>
</ul>
</div>
<div class="col-6 p-0">
This is absolute positioned because the layout require the image to go outside of container until the page end, with no height setted because of responsive and dynamism.
<img src="https://picsum.photos/956/870">
</div>
</div>
</div>
</section>

CSS Truncate inline text only if needed

I'm trying to style a reusable component such that it will stay inline but truncate its contents whenever it overflows. What makes it trickier is that I need to have an icon on the right.
The main issue is that I need the icon to stay on the same line, so I compensate for it in the width of the truncated text (width: calc(100% - 40px)), which makes any non-truncating example be that much shorter than it's normal width.
See the snippet below and how the short example is barely visible.
body, .container {
width: 100%;
padding: 0;
margin: 50px 0;
}
.quantity-value {
display: inline-block;
max-width: 100%;
margin-right: 16px;
background: #f1f1f1;
}
.value-and-icon-wrapper {
display: inline-block;
width: 100%;
}
.icon {
padding-left: 5px;
}
.truncated-text {
display: inline-block;
width: calc(100% - 40px);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
vertical-align: top;
-webkit-line-clamp: 1;
}
<!-- Example 1: short -->
<div class="container">
<div class="quantity-value">
<div class="value-and-icon-wrapper">
<span class="truncated-text">67</span>
<span class="icon">ℹ️</span>
</div>
</div>
other content
</div>
<!-- Example 2: long -->
<div class="container">
<div class="quantity-value">
<div class="value-and-icon-wrapper">
<span class="truncated-text">68 long text starting now lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet</span>
<span class="icon">ℹ️</span>
</div>
</div>
other content
</div>
This is because you are using a lot of inline-block and the width of inline-block is defined by its content so if you set 100% - 40px for a child item, it means its width minus 40px
Try to do it differently like below using flexbox:
body, .container {
width: 100%;
padding: 0;
margin: 50px 0;
}
.quantity-value {
display: inline-flex;
max-width: calc(100% - 16px); /* don't forget to account for margin here */
margin-right: 16px;
background: #f1f1f1;
}
.icon {
padding-left: 5px;
}
.truncated-text {
flex:1;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<!-- Example 1: short -->
<div class="container">
<div class="quantity-value">
<span class="truncated-text">67</span>
<span class="icon">ℹ️</span>
</div>
other content
</div>
<!-- Example 2: long -->
<div class="container">
<div class="quantity-value">
<span class="truncated-text">68 long text starting now lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet</span>
<span class="icon">ℹ️</span>
</div>
other content
</div>
Without flexbox you can do it like below:
body, .container {
margin: 50px 0;
}
.quantity-value {
display: inline-block;
max-width: calc(100% - 16px); /* don't forget to account for margin/padding here */
margin-right: 16px;
background: #f1f1f1;
padding-right:20px;
box-sizing:border-box;
position:relative;
}
.icon {
padding-left: 5px;
position:absolute;
right:0;
top:0;
bottom:0;
}
.truncated-text {
display:block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<!-- Example 1: short -->
<div class="container">
<div class="quantity-value">
<span class="truncated-text">67</span>
<span class="icon">ℹ️</span>
</div>
other content
</div>
<!-- Example 2: long -->
<div class="container">
<div class="quantity-value">
<span class="truncated-text">68 long text starting now lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet</span>
<span class="icon">ℹ️</span>
</div>
other content
</div>
Try applying the style text-overflow: ellipsis to the div that contains the text to be truncated.
MDN Documentation for text-overflow

Left align text below center aligned text

I am wondering if it is possible to left align text below center aligned text, so that both texts start from same position.
In the example figure. The TITLEs are center aligned and the copy below is left aligned.
How can you realise something like this with CSS?
Here is a JSFiddle to start from
https://jsfiddle.net/j5p7v8m9/
<div>
<p style="text-align: center;">TITLE</p>
<p style="text-align: left;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
Here is the answer. I've updated your JSFiddle. You need to add some wrappers for each divs, then you can centerize the title as follows:
HTML:
<div class="container">
<div class="col">
<div class="contents">
<p class="title">TITLE</p>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
</div>
<div class="col">
<div class="contents">
<p class="title">TITLE</p>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
</div>
<div class="col">
<div class="contents">
<p class="title">TITLE</p>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
</div>
</div>
CSS:
.container{
display: block;
}
.col{
float: left;
width: 33.33%;
}
.contents{
margin-left: 20px;
margin-right: 20px;
}
.title{
text-align: center;
}
JSFiddle: https://jsfiddle.net/53oLpvqg/
Please try with bootstrap css it my help you for easy css.
<div class="col">
<p class="text-center">Title</p>
<p class="text-left">Test content Content</p>
</div>
Check Fiddle https://jsfiddle.net/0h2nmj3r/
*Look at other answers for directions on align text this is answer will help with getting that column effect
The best way to get three columns like that is to use a type of special display in css called "flex". Flex allows you to easily align elements within the parent html element.
.container{
display:flex;
flex-direction : row;
justify-content: space-around;
}
.text-box{
display: flex;
flex-direction:column;
align-items:flex-start;
width:20%;
}
p{
margin: 0 0 5px 0;
}
<div class="container">
<div class="text-box">
<p >TITLE</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
<div class="text-box">
<p >TITLE</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
<div class="text-box">
<p >TITLE</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
</div>
So as you can see I have applied flex to both the container and the text-box's. Left align can be used like in these other answers but i opted for align-items:flex-start so any element within the text-box will be aligned to the left.
By setting justify-content:space-around it makes each element within the container have equal space around it so if you were to change the window size the spaces would be relative and change. I would recommend studying more about flex and grid to improve your css skills.

How to custom align content in columns but keep text left aligned?

I'm trying to align text content in a column. I don't know how I can align the whole content to the center or to the right of the column and keep the text content left aligned.
I have added an example to jsfiddle: https://jsfiddle.net/k58vr4nq/
Currently the colums looks like this:
|-----------------------------------------------|
|Lorem ipsum |Lorem ipsum |Lorem ipsum |
|dolor sit |dolor sit |dolor sit |
|amet |amet |amet |
|consetetur |consetetur |consetetur |
|sadipscing |sadipscing |sadipscing |
|-----------------------------------------------|
I'm expecting something like this:
|-----------------------------------------------|
|Lorem ipsum | Lorem ipsum | Lorem ipsum|
|dolor sit | dolor sit | dolor sit |
|amet | amet | amet |
|consetetur | consetetur | consetetur |
|sadipscing | sadipscing | sadipscing |
|-----------------------------------------------|
First, you add your text for each column in div, so it becomes element with width of widest text line. Then, you use flexbox on parent (col element) and align the divs however you want.
HTML:
<div class="container">
<div class="row">
<div class="col text-container left">
<div>
Lorem ipsum<br/>
dolor sit<br/>
amet<br/>
consetetur<br/>
sadipscing<br/>
</div>
</div>
<div class="col text-container middle">
<div>
Lorem ipsum<br/>
dolor sit<br/>
amet<br/>
consetetur<br/>
sadipscing<br/>
</div>
</div>
<div class="col text-container right">
<div>
Lorem ipsum<br/>
dolor sit<br/>
amet<br/>
consetetur<br/>
sadipscing<br/>
</div>
</div>
</div>
</div>
and CSS:
.col {
border: solid 1px #6c757d;
}
.text-container {
display: flex;
}
.middle {
justify-content: center;
}
.right {
justify-content: flex-end;
}
Here's jsfiddle of complete solution: https://jsfiddle.net/7vetqkrz/
For that purpose, you would have to wrap your col content inside an element:
<div class="col">
<div class="content">
Lorem ipsum<br/>
dolor sit<br/>
amet<br/>
consetetur<br/>
sadipscing<br/>
</div>
</div>
Then you would have to style that content class with some margin:
.content {
margin-left: 1rem;
}
Fiddle: https://jsfiddle.net/2ukyqo7m/4/
Add your content into a block with display: inline-block so it fits to size, align within that block, then align the block.
See below (I wouldn't do it inline, it's there to show what's going on):
Here's your fiddle updated
<div class="container">
<div class="row">
<div class="col">
<div style="display: inline-block; text-align: left">
Lorem ipsum<br/> dolor sit<br/> amet
<br/> consetetur
<br/> sadipscing
<br/>
</div>
</div>
<div class="col text-center">
<div style="display: inline-block; text-align: left">
Lorem ipsum<br/> dolor sit<br/> amet
<br/> consetetur
<br/> sadipscing
<br/>
</div>
</div>
<div class="col text-right">
<div style="display: inline-block; text-align: left">
Lorem ipsum<br/> dolor sit<br/> amet
<br/> consetetur
<br/> sadipscing
<br/>
</div>
</div>
</div>
</div>
add to CSS
.text-center{
text-align: left;
padding-left: 1em;
}
.text-right{
}