Hide divs simultaneously depending on the largest size - javascript

I have two divs. Inside each div, there are two divs:
<div class="hide">
<div>
Variable size
</div>
<div>
Text1 (also variable size)
</div>
</div>
<div class="hide">
<div>
Different variable size
</div>
<div>
Text2 (also variable size)
</div>
</div>
If the screen is too small, I want the texts to disappear:
To do it, I used
.hide {
display: flex;
height: 100px;
flex-wrap: wrap;
overflow: hidden;
}
However, if the 1st text is too big, but the second is not, I have something like that:
And I'd like them to be hidden simultaneously.
Is there a way (no jQuery) to do it? Preferably with CSS or SASS, but JS (I use Angular) would also be acceptable.

Use display flex like this
.hide { height: 100px; display: flex; flex-wrap: wrap; overflow: hidden; }

Related

how to get/set component size dynamically

I have a DIV container that has a paragraph and another inner DIV displayed in line.
Inner DIV is unknown but it's always the same and not gonna change. I can sent min-width if needed. Now based on outer DIV size I need to either cut (with three dots) or show full paragraph string. But I have to set paragraph width in css to show that three dots when outer div size is too small.
<div className="divOuter">
<p>very long string</p>
<div className="divInner">some div stuff</div>
</div>
.p {
position: relative;
float: left;
text-overflow: ellipsis;
overflow: hidden;
width: ?????; // what do I set here?????
white-space: nowrap;
}
.divInner {
display: flex;
float: right;
align-items: center;
}
|--------------------------------------|
|very long string some div stuff|
|--------------------------------------|
need to get this when outer DIV resized:
|------------------------------|
|very long st... some div stuff|
|------------------------------|
|--------------------|
|ve... some div stuff|
|--------------------|
This is what you are looking for.
You don't need to give any width to the long string p element.
There is a property of flexbox called flex. When you set this to 1, it will elongate that element to take up the remaining horizontal space in the parent.
After that, you just have to give text-overflow: ellipsis; overflow: hidden; to make the ... appear.
Run the below snippet to see it working.
.divOuter {
display: flex;
width: 100%;
}
.longString {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.divInner {}
<div class="divOuter">
<p class="longString">very long string very long string very long string very long string very long string</p>
<p class="divInner">some div stuff</p>
</div>

Overflow-x position on right

I have one paragraph p where I need to display some data.
I set white-space:nowrap and text-align:right. When someone types some content in one text field, this content shows in the paragraph from right to left.
But when data comes to left scroll-x was set to left, and to see new typed content you need to scroll to right.
I need the reverse, showing new content and scroll if you want to see the old one.
If i use direction: rtl, it works fine, but only for word, not with number, so i need another solution. Ofc i have an idea to do this with javascript, but i want solution without it.
document.querySelector('#inpt').addEventListener('keydown', function(e) {
document.querySelector('#display').innerHTML = e.target.value
})
p {
width: 100%;
white-space: nowrap;
text-align: right;
overflow-x: scroll;
}
<input id="inpt" type="text">
<p id='display'>
</p>
Setting display: flex with a flex-direction of row-reverse on your p tag seems to do the trick:
document.querySelector('#inpt').addEventListener('keydown', function(e) {
document.querySelector('#display').innerHTML = e.target.value
})
p {
display: flex;
flex-direction: row-reverse;
width: 100%;
white-space: nowrap;
text-align: right;
overflow-x: scroll;
}
<input id="inpt" type="text">
<p id='display'>
</p>

Break all lines in CSS if one breaks

I've a part of code on my website. Some time it can happen that the line breaks if the code don't fit in the parent element anymore:
If this happens I want to break all lines instead because it looks ugly when one part is broken and the other don't.
Remind
I can have a least 20 elements in one list.
Update
This is the part of my code which I all need to wrap if one of them wraps:
.elements-list {
display: -webkit-box;
display: flex;
display: -ms-flexbox;
list-style: none outside;
}
.list-entry {
display: -webkit-box;
display: flex;
display: -ms-flexbox;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
list-style: none outside;
padding-right: 8px;
max-width: 200px;
}
span.single-detail span {
letter-spacing: 1px;
display: -webkit-inline-box;
display: inline-flex;
display: -ms-inline-flexbox;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
<ul class="elements-list">
<li class="list-entry">
<span class="single-detail">
<span>Abgabefrist:</span>
<span>22.02.2222</span>
</span>
<span class="single-detail">
<span>Entlohnung:</span>
<span>2.222,00 €</span>
</span>
</li>
<li class="list-entry">
<span class="single-detail">
<span>Abgabefrist:</span>
<span>22.02.2222</span>
</span>
<span class="single-detail">
<span>Entlohnung:</span>
<span>20.222,00 €</span>
</span>
</li>
<li class="list-entry">
<span class="single-detail">
<span>Abgabefrist:</span>
<span>22.02.2222</span>
</span>
<span class="single-detail">
<span>Entlohnung:</span>
<span>22.000.222,00 €</span>
</span>
</li>
</ul>
I don't think you can solve this with CSS alone. You can solve it with JavaScript.
One way would be to constantly monitor the elements and see if one of them wrapped. But then, once wrapped you will never unwrap, it's not responsive.
So this is my alternative:
By putting the value inside inline-block elements, you can align the widths of the elements. This way, when one element wraps, they will all wrap, because they simply won't fit anymore.
Advantages of this solution:
It's responsive, responds to browser resizing.
Only requires JavaScript on load. Sizing and wrapping is handled by CSS once the widths are set, so it's fairly lightweight.
Disadvantages:
You will need to recalculate the widths if you change the content of the elements, or if you have dynamic font sizing (I hope not).
It's not pixel perfect, it seems. Maybe it can be tuned (for instance by giving the left element also a width in whole pixels), or otherwise, maybe you'll forgive me this pixel. ;)
window.addEventListener('DOMContentLoaded', function(){
var rows = document.querySelectorAll('.row');
// First loop to find which line is the widest.
var widest = 0;
for(r=0; r<rows.length; r++) {
console.log(r);
var width = rows[r].querySelector('.col1').offsetWidth +
rows[r].querySelector('.col2').offsetWidth;
if (width > widest) widest = width;
}
// second loop to set the width of col2, so they all
// get the same width.
for(r=0; r<rows.length; r++) {
rows[r].querySelector('.col2').style.width =
(widest - rows[r].querySelector('.col1').offsetWidth) + 'px';
}
});
/* This is needed */
.col2 {
display: inline-block;
}
/* This is just for show */
.col1 {
padding-right: 1em;
}
span {
box-sizing: border-box;
border: 1px solid grey;
}
<!-- hacky div/span table, since there is no HTML in the question -->
<div class="row"><span class="col1">The time</span><span class="col2">2018-12-22 12:34</span></div>
<div class="row"><span class="col1">Total price here</span><span class="col2">$ 5,-</span></div>
You either need to set the css property white-space: nowrap; on the text parent element so no text wraps for that class or you could add the <br> on the HTML after the name of the element so it breaks every time, code is needed so we can be more specific in finding a solution.
Well, easiest would be to create "abgabefrist:01/01/0001" as two elements instead of one and then add display flex to the parent. so when the screen shrinks, the element comes below another.
Below mentioned code fine, tested on codepen.
.dates div {
display: flex;
flex-wrap: wrap;
}
<div class="main">
<div class="dates">
<div><span>abgabefrist:</span>
<span>01/01/0001</span></div>
<div><span>abgabefrist:</span>
<span>02/02/0002</span></div>
</div>
<div class="btns">
<button> Button One</button>
<button> Button Two </button>
</div>
</div>

Keep the same flex-growth between lines [duplicate]

My problem is that I want the flexbox with variable range width, and all works well, but not on the last row. I want the same dimension for all children even where the row is not full of children (the last row).
#products-list {
position:relative;
display: flex;
flex-flow: row wrap;
width:100%;
}
#products-list .product {
min-width:150px;
max-width:250px;
margin:10px 10px 20px 10px;
flex:1;
}
I created a dynamic situation in jsFiddle
My flex divs can shrink until 150px and grow up to 250px, but all must be with the same size (and obviously I want a CSS solution, with JS I know the way).
Unfortunately, in the current iteration of flexbox (Level 1), there is no clean way to solve the last-row alignment problem. It's a common problem.
It would be useful to have a flex property along the lines of:
last-row
last-column
only-child-in-a-row
alone-in-a-column
This problem does appear to be a high priority for Flexbox Level 2:
CSS Working Group Wiki - Specification Issues and Planning
https://lists.w3.org/Archives/Public/www-style/2015Jan/0150.html
Although this behavior is difficult to achieve in flexbox, it's simple and easy in CSS Grid Layout:
Equal width flex items even after they wrap
In case Grid is not an option, here's a list of similar questions containing various flexbox hacks:
Properly sizing and aligning the flex item(s) on the last row
Flex-box: Align last row to grid
Flexbox wrap - different alignment for last row
How can a flex item keep the same dimensions when it is forced to a new row?
Selector for an element alone in a row?
Aligning elements in last flexbox row
How can I allow flex-items to grow while keeping the same size?
Left-align last row of flexbox using space-between and margins
Inconsistent margin between flex items on last row
How to keep wrapped flex-items the same width as the elements on the previous row?
How to align left last row/line in multiple line flexbox
Last children of grid get giant gutter cause of flexbox space-between
Managing justify-content: space-between on last row
Flexbox space between behavior combined with wrap
Possible to use CSS Flexbox to stretch elements on every row while maintaining consistent widths?
As a quick and dirty solution one can use:
.my-flex-child:last-child/*.product:last-child*/ {
flex-grow: 100;/*Or any number big enough*/
}
You could try using grid instead of flexbox here:
#products-list {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fit, minmax(100px, 250px)); //grid automagic
justify-content: start; //start left
}
Fiddle link
There is a great solution that works always.
add a div with class product (The same class for other items that are under flex) and add a style for this div:height:0px;
you need to add as many dives that are possible to be in one row.
<div class="product" style="height:0px">
as many that can be in one row.
That's all. Works always.
If all your rows have the same number of items, you can use :nth-last-child. For example, if all the rows have 3 items, you can do something like this to remove the margin of the last 3 items:
.container{
display: flex;
flex-wrap: wrap;
background: yellow;
}
.item{
width: calc((100% - 2*10px)/3);
height: 50px;
background: blue;
color: white;
margin-right: 10px;
margin-bottom: 10px;
padding: 5px;
box-sizing: border-box;
}
/* last item of each row */
.item:nth-child(3n){
margin-right: 0;
font-size: 150%;
}
/* last 3 items */
.item:nth-last-child(-n+3){
margin-bottom: 0;
background: green;
}
<div class="container">
<div class="item" >1</div>
<div class="item" >2</div>
<div class="item" >3</div>
<div class="item" >4</div>
<div class="item" >5</div>
<div class="item" >6</div>
<div class="item" >7</div>
</div>
A simple trick adds a flexible space to fill the rest of the last row:
#products-list{
display:flex;
flex-flow: row wrap;
justify-content:space-between;
}
#products-list::after {
content: "";
flex: auto;
flex-basis: 200px;/*your item width*/
flex-grow: 0;
}
But you shouldn't use margins on items then. Rather wrap them into containers with padding.
I used this workaround, even if it's not very elegant and it doesn't use the power of Flexbox.
It can be carried out on the following conditions:
All the items have the same width
The items have a fixed width
You use SCSS/SASS (can be avoided though)
If this is the case, you can use the following snippet:
$itemWidth: 400px;
$itemMargin: 10px;
html, body {
margin: 0;
padding: 0;
}
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 auto;
border: solid 1px blue;
}
#for $i from 1 through 10 {
#media only screen and (min-width: $i * $itemWidth + 2 * $i * $itemMargin) {
.flex-container {
width: $i * $itemWidth + 2 * $i * $itemMargin;
}
}
}
.item {
flex: 0 0 $itemWidth;
height: 100px;
margin: $itemMargin;
background: red;
}
<div class="flex-container">
<div class="item"></div>
<div class="item" style="flex: 500 0 200px"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Here I have created an example on codepen which also implements margin.
The second and the third conditions can be avoided respectively using css variables (if you decided to provide support for it) and compiling the above scss snippet.
Well, it's true, we could do it also before flexbox, but display: flex can be still essential for a responsive design.
I was facing this same issue where I wanted to have a variable number of items in a resizable container.
I wanted to use all of the horizontal space, but have all of the flex items at the same size.
I ultimately came up with a javascript approach that dynamically added padding spacers as the container was resized.
function padLastFormRow() {
let topList = [];
let nSpacersToAdd = 0;
$('#flexContainer').find('.formSpacer').remove();
$('#flexContainer').find('.formItem').each(function(i, formItem) {
topList.push($(formItem).position().top);
});
let allRowLengths = getFlexLineLengths(topList);
let firstRowLength = allRowLengths[0];
let lastRowLength = allRowLengths[((allRowLengths.length) - 1)];
if (lastRowLength < firstRowLength) {
nSpacersToAdd = firstRowLength - lastRowLength ;
}
for (var i = 1; i <= nSpacersToAdd; i ++) {
$('#flexContainer').append(formSpacerItem);
}
}
Please see my Fiddle:
http://jsfiddle.net/Harold_Buchman/z5r3ogye/11/
I was having a similar challenge with menu rows. I wanted more spacing on the top of the second row of menu items.
The use of flex-box's row-gap worked well.
https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap
.menu {
display: flex;
flex-wrap: wrap;
row-gap: 10px;
}
This added a margin-top type effect to menu items were wrapped to the second line.
If all your rows have the same number of items, you can use :nth-last-child. For example, if all the rows have 3 items, you can do something like this:
.container{
display: flex;
flex-wrap: wrap;
background: yellow;
}
.item{
width: calc((100% - 2*10px)/3);
height: 50px;
background: blue;
color: white;
margin-right: 10px;
margin-bottom: 10px;
padding: 5px;
box-sizing: border-box;
}
// last item of each row
.item:nth-child(3n){
margin-right: 0;
background: green;
}
// last 3 items
.item:nth-last-child(-n+3){
margin-bottom: 0;
font-size: 150%;
}
<div class="container">
<div class="item" >1</div>
<div class="item" >2</div>
<div class="item" >3</div>
<div class="item" >4</div>
<div class="item" >5</div>
<div class="item" >6</div>
<div class="item" >7</div>
</div>

Make Buttons stay inline-block when toggled

I've got 3 categories acting as buttons for a toggle function. The categories are
displayed inline-block and have a width of 30% each.
When you click on one of them a paragraph appears underneath, however that causes the other two categories to be displayed underneath that paragraph. I need them to stay in one line though.
Here's the fiddle so you can see what I mean. When you click on 'Test1' the 'Test2' is moved underneath the paragraph but I need it to stay where it is.
Any suggestions how to achieve this?
Edit
I've got the html structure like this as it makes the layout work for mobile devices where the categories are stacked.
I've changed your HTML structure, see this fiddle
HTML:
<div class="Categories">
<p id="Category1">Test1</p>
<p id="Category2">Test2</p>
</div>
CSS:
.Categories p {
width:33%;
display:inline-block;
}
JS :
$('#Category1').click(function(){
$('.moreCategory1').toggle();
});
$('#Category2').click(function(){
$('.moreCategory2').toggle();
});
This problem is easily solved by using a flex container. Not only it solves your problem, it is also easy to change for mobile in responsive web design and it is semantically correct.
HTML:
<div class="categories">
<p id="Category1">Test1</p>
<p id="Category2">Test2</p>
<p id="Category3">Test3</p>
</div>
<div id="more1" class="moreCategory">
<p>Content 1</p>
</div>
<div id="more2" class="moreCategory">
<p>Content 2</p>
</div>
<div id="more3" class="moreCategory">
<p>Content 3</p>
</div>
CSS:
.categories {
display: flex;
width: 100%; /*Not necessary. Make sure its large enough to be clear*/
flex-direction: row;
}
.categories p {
width: 30%;
margin: 2px;
padding: 3px;
text-align: center;
background-color: #000;
color: #fff;
}
.moreCategory {
display: none;
}
For Mobile:
#media (min-width: 600px) {
.categories {
flex-direction: column;
}
.categories p {
width: 100%;
}
}
JQuery:
$('#Category1').click(function() {
if ($('#more1').is(":hidden")) $('#more1').toggle();
if (!$('#more2').is(":hidden")) $('#more2').toggle();
if (!$('#more3').is(":hidden")) $('#more3').toggle();
});
$('#Category2').click(function() {
if (!$('#more1').is(":hidden")) $('#more1').toggle();
if ($('#more2').is(":hidden")) $('#more2').toggle();
if (!$('#more3').is(":hidden")) $('#more3').toggle();
});
$('#Category3').click(function() {
if ($('#more1').is(":hidden")) $('#more1').toggle();
if (!$('#more2').is(":hidden")) $('#more2').toggle();
if (!$('#more3').is(":hidden")) $('#more3').toggle();
});
This should solve your problem. JS Fiddle.
EDIT :
If you really want the heading tabs together, but also applicable for mobile you can hide the selecting controller from my for, i.e., the topmost main div.
Hide the header tags for large screens and the same css applies. For mobiles, hide the control div and show the headers and moreContent divs without any JQuery controls. A simple if statement should do the trick(check for screen size or user agent).

Categories

Resources