Make rows expand to scrollable parent's width - javascript

I’m making a table-like layout using flexbox.
It has a body, rows and cells.
Cells have the fixed widths in pixels.
Body should be horizontally scrollable.
I would like to achieve that rows have the same width as cumulative widths of cells.
Here’s the codepen.
<div class="grand-parent">
<div class="parent">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
<div class="child">Child 3</div>
</div>
<div>
Is there any way to do this using CSS only?
P.S. I know I can calculate the widths using JS and set that to parent, or I can set the background color to grand-parent to make it look nicer, but that's not what I need here.

one way is to not fix size on child component but use flex-grow: 1; to let them take all available size
.child {
flex-grow: 1;
color: white;
background: blue;
border: 1px solid black;
}
OR
if you want to force container to take child width you have to :
.child have display: inline-flex;
.parent have width: max-content;
.parent {
background: red;
padding: 2em 0;
width: max-content;
}
.child {
display: inline-flex;
width: 300px;
color: white;
background: blue;
border: 1px solid black;
}
following the running snippet of this reply
.grand-parent {
width: 800px;
overflow: auto;
}
.parent {
display: flex;
background: red;
padding: 2em 0;
}
.child {
flex-grow:1;
color: white;
background: blue;
border: 1px solid black;
}
.parent2 {
background: red;
padding: 2em 0;
width: max-content;
}
.child2 {
display: inline-flex;
width: 300px;
color: white;
background: blue;
border: 1px solid black;
}
::-webkit-scrollbar {
-webkit-appearance: none;
width: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0, 0, 0, .5);
box-shadow: 0 0 1px rgba(255, 255, 255, .5);
}
<h1> child take width of parent</h1>
<div class="grand-parent">
<div class="parent">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
<div class="child">Child 3</div>
</div>
<div>
<h1> parent take width of child</h1>
<div class="grand-parent">
<div class="parent2">
<div class="child2">Child 1</div>
<div class="child2">Child 2</div>
<div class="child2">Child 3</div>
</div>
<div class="parent2">
<div class="child2">Child 1</div>
<div class="child2">Child 2</div>
<div class="child2">Child 3</div>
</div>
<div>

Well, just like Jeremy's answer, you can set them to take available space
OR
Instead of making the grand-parent fixed-width, you can set the parent to be of fixed width;
.parent {
display: flex;
background: red;
padding: 2em 0;
width: 800px;
overflow: auto;
}
I took all the styles of grand-parent and added the to the style of parent
The following snippet works perfectly fine:
.parent {
display: flex;
background: red;
padding: 2em 0;
width: 800px;
overflow: auto;
}
.child {
flex: 0 0 300px;
color: white;
background: blue;
border: 1px solid black;
}
<div class="grand-parent">
<div class="parent">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
<div class="child">Child 3</div>
</div>
</div>

Related

CSS : Create Process Steps Style

I am new to CSS.
I want to create a Process Step Like in the image.
Below is the code I have tried.
.inline-div{
padding: 1rem;
border: 0.04rem gray solid;
display: inline-block;
width: 25%;
border-top-left-radius: 25px;
}
.active{
background: #8b7b38;
color: #FFFFFF;
}
<div>
<div class="inline-div">Text A</div>
<div class="inline-div active">Text B</div>
<div class="inline-div">Text C</div>
</div>
Any help would be great.
Thank You.
try this instead,
Remove the gap between each process by using flex
.main{
flex-wrap:nowrap;
display: flex;
}
And to remove all border-left of inline-div except first item.
.inline-div:not(:first-child){
margin-left:-0.04rem; // to remove the left border
}
.inline-div{
padding: 1rem;
border: 0.04rem gray solid;
width: 25%;
border-top-left-radius: 25px;
}
.inline-div:not(:first-child){
margin-left:-0.04rem; // to remove the left border
}
.main{
flex-wrap:nowrap;
display: flex;
}
.active{
background: #8b7b38;
color: #FFFFFF;
}
.inline-div {}
<div class="main">
<div class="inline-div">Text A</div>
<div class="inline-div active">Text B</div>
<div class="inline-div">Text C</div>
<div class="inline-div">Text D</div>
</div>
set outer div's font-size to zero to remove the gap between each 2 steps, set right step's margin-left to negative border width to overlap left step's border, then it'll work fine:
.outer-div{
font-size: 0;
}
.inline-div{
padding: 1rem;
border: 0.04rem gray solid;
display: inline-block;
width: 25%;
border-top-left-radius: 25px;
text-align: center;
font-size: 20px; /* set inner div's font-size as you need */
}
.active{
background: #8b7b38;
color: #FFFFFF;
}
.no-left-border{
margin-left: -0.04rem;
}
<div class="outer-div">
<div class="inline-div">Text A</div>
<div class="inline-div active no-left-border">Text B</div>
<div class="inline-div no-left-border">Text C</div>
</div>
.inline-div{
padding: 1rem;
border: 0.04rem gray solid;
display: inline-block;
width: 25%;
border-top-left-radius: 25px;
background-color: transparent;
}
.active{
background: #8b7b38;
color: #FFFFFF;
}
.flex-div {
display: flex;
background: blue; // change to your color
}
<div class="flex-div">
<div class="inline-div">Text A</div>
<div class="inline-div active">Text B</div>
<div class="inline-div">Text C</div>
</div>

Dragula - Drag elements from multiple container to destination container

I have got 4 containers, where first 3 are the source containers and the elements are to be added in the 4th container(destination container). The elements from the source containers shouldn't allow to drop the elements to the neighboring containers expect for the destination containers and the elements dropped in the destination containers can dropped back to its respective containers.
here's my code
dragula([document.getElementById('col1'),document.getElementById('col2'),document.getElementById('col3'), document.getElementById('done')],{
accepts: function (el, target, source, sibling) {
return target == document.getElementById('done') ;
});
.wrapper{ display: table;}
.container {
border: 2px dotted #ccc;
border-radius: 5px;
width: 250px;
padding: 10px;
display: table-cell;
margin-left: 20px;
position:relative;
text-align:center
}
.container div {
border: 2px solid #f3f3f3;
border-radius: 5px;
margin: 10px;
width: 200px;
padding: 10px;
color: #000;
cursor: move;
}
.vl:after {
content:"";
position: absolute;
z-index: -1;
top: 0;
bottom: 0;
left: 50%;
border-left: 6px solid green;
transform: translate(-50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.js"></script>
<div class="wrapper">
<div id="col1" class="container">
<div>Mango 1</div>
<div>Mango 2</div>
<div>Mango 3</div>
</div>
<div id="col2" class="container">
<div>Guava 1</div>
<div>Guava 2</div>
<div>Guava 3</div>
</div>
<div id="col3" class="container">
<div>Peach 1</div>
<div>Peach 2</div>
<div>Peach 3</div>
</div>
<div id="done" class="container vl">
</div>
</div>

Create floating elements with css rule on odd elements and display none / block in HTML / CSS

I am doing a program with a list of elements (float or flex) that might have a display of "none", that can change dynamically. I manage to do it in CSS when it is defined with a selector :
div:nth-child(odd)
However if I hide one div, it doesn't work anymore. I tried something like
div[style*="display: block;"]:nth-child(odd)
but breaks.
* {box-sizing: border-box;}
.flex-container {
width: 90%;
margin: 5px auto;
display: flex;
background-color: #ddd;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: stretch;
}
.flex-container>div {
background-color: #f1f1f1;
display: block;
padding: 5px;
font-size: 12px;
cursor: pointer;
text-align: center;
width: 50%;
border-bottom: solid 1px #ccc;
}
.flex-container>div[style*="display: block;"]:nth-child(odd) {
border-right: solid 1px red;
}
<div class="flex-container">
<div id="flex1" style="display: block;">TEST 1</div>
<div id="flex2" style="display: block;">TEST 2</div>
<div id="flex3" style="display: block;">TEST 3</div>
<div id="flex4" style="display: block;">TEST 4</div>
<div id="flex5" style="display: block;">TEST 5</div>
</div>
<input type="button" onclick="document.getElementById('flex1').style.display = document.getElementById('flex1').style.display === 'none' ? 'block' : 'none'" value="Flex1" />
When using the button, it shows / hides the first div. What I would like is to have this red border always in the middle.
I would like to avoid using javascript as much as possible.
Maybe I got it completely wrong, or it isn't feasible without javascript.
No need to complicate with nth-child. You can simply draw a line in the middle using pseudo element. Also read the following to understand why your code doesn't work: Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
* {box-sizing: border-box;}
.flex-container {
width: 90%;
margin: 5px auto;
display: flex;
background-color: #ddd;
flex-wrap: wrap;
position:relative;
}
.flex-container:before {
content:"";
position:absolute;
top:0;
bottom:0;
left:50%;
width:1px;
background:red;
}
.flex-container>div {
background-color: #f1f1f1;
padding: 5px;
font-size: 12px;
cursor: pointer;
text-align: center;
width: 50%;
border-bottom: solid 1px #ccc;
}
<div class="flex-container">
<div id="flex1" style="display: block;">TEST 1</div>
<div id="flex2" style="display: block;">TEST 2</div>
<div id="flex3" style="display: block;">TEST 3</div>
<div id="flex4" style="display: block;">TEST 4</div>
<div id="flex5" style="display: block;">TEST 5</div>
</div>
<input type="button" onclick="document.getElementById('flex1').style.display = document.getElementById('flex1').style.display === 'none' ? 'block' : 'none'" value="Flex1" />
Here is another idea using CSS grid:
* {box-sizing: border-box;}
.flex-container {
width: 90%;
margin: 5px auto;
display: grid;
grid-template-columns:1fr 1fr;
grid-column-gap:1px;
background:
linear-gradient(red,red) center/1px 100% no-repeat,
#ddd;
}
.flex-container>div {
background-color: #f1f1f1;
padding: 5px;
font-size: 12px;
cursor: pointer;
text-align: center;
border-bottom: solid 1px #ccc;
}
<div class="flex-container">
<div id="flex1" style="display: block;">TEST 1</div>
<div id="flex2" style="display: block;">TEST 2</div>
<div id="flex3" style="display: block;">TEST 3</div>
<div id="flex4" style="display: block;">TEST 4</div>
<div id="flex5" style="display: block;">TEST 5</div>
</div>
<input type="button" onclick="document.getElementById('flex1').style.display = document.getElementById('flex1').style.display === 'none' ? 'block' : 'none'" value="Flex1" />

white spacing between my columns can't overwrite it using css and can't see the css on it showing space

I have a set of columns with some sliding i am doing between them but then when i arranged them to look like how in my fiddle i found a space between each of them
This is my fiddle, how I can get rid of this spacing to make them attached to each others?
$(document).ready(function() {
jQuery("#switcher1").click(function() {
jQuery(".middle-wrap").animate({left: "0px"});
});
jQuery("#switcher2").click(function() {
jQuery(".middle-wrap").animate({left: "-198.4px"});
});
jQuery("#switcher3").click(function() {
jQuery(".middle-wrap").animate({left: "-396.8px"});
});
jQuery("#switcher4").click(function() {
jQuery(".middle-wrap").animate({left: "-595.2px"});
});
jQuery("#switcher5").click(function() {
jQuery(".middle-wrap").animate({left: "-793.6px"});
});
jQuery("#switcher6").click(function() {
jQuery(".middle-wrap").animate({left: "-992px"});
});
jQuery("#switcher7").click(function() {
jQuery(".middle-wrap").animate({left: "-1190.4px"});
});
jQuery("#switcher8").click(function() {
jQuery(".middle-wrap").animate({left: "-1388.8px"});
});
});
.outer-wrap {
overflow-x: hidden;
position: relative;
max-width: 1050px;
min-width: 1050px;
margin: 0;
padding: 0;
height: 450px;
background-color: #fff;
-webkit-border-radius: 5px;
border-radius: 5px;
border: 1px solid #e3e3e3;
display: inline-block;
background-color: #fff;
border-top: 1px solid #e3e3e3;
transition: all 50ms ease-in-out;
}
.middle-wrap {
position: relative;
max-width: 1890px;
left: 0px;
margin: 0;
padding: 0;
height: 450px;
min-width: 1890px;
}
.inner-wrap {
display: inline-block;
max-width: 210px;
min-width: 210px;
border-right: 1px solid #e3e3e3;
vertical-align: top;
border: none;
margin: 0;
padding: 0;
height: 100%;
/* float: left;*/
}
.year_list {
background-color: darksalmon;
}
.make_list {
background-color: red;
}
.model_list {
background-color: aquamarine;
}
.body_style {
background-color: blue;
}
.transmission {
background-color:darkviolet;
}
.options {
background-color: darkslategray;
}
.aftermarket_modifications {
background-color: darkseagreen;
}
.mileage {
background-color: darkred;
}
.license_plate {
background-color: darkorange;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<div id="switcher1">See Part 1</div>
<div id="switcher2">See Part 2</div>
<div id="switcher3">See Part 3</div>
<div id="switcher4">See Part 4</div>
<div id="switcher5">See Part 5</div>
<div id="switcher6">See Part 6</div>
<div id="switcher7">See Part 7</div>
<div id="switcher8">See Part 8</div>
<div class="outer-wrap">
<div class="middle-wrap">
<div class="inner-wrap year_list"></div>
<div class="inner-wrap make_list"></div>
<div class="inner-wrap model_list"></div>
<div class="inner-wrap body_style"></div>
<div class="inner-wrap transmission"></div>
<div class="inner-wrap options"></div>
<div class="inner-wrap aftermarket_modifications"></div>
<div class="inner-wrap mileage"></div>
</div>
</div>
Due to your display: inline-blocks, the white spaces appear in between your block elements.
There are many resolutions to the same, refer to David Walsh's blog
What I would prefer to do here is use float instead of display: inline-block.
Check updated fiddle: https://jsfiddle.net/b6fw4u0z/2/
Uncomment float: left in .inner-wrap styling
jsfiddle
If you have to use display: inline-block then to remove the white space between elements, you can set
font-size: 0
to them.
See updated fiddle:
https://jsfiddle.net/b6fw4u0z/3/
You will notice i just put it on all the nested divs.

text-overflow: ellipsis and flex

I have a container element with display: flex property set.
A children have fixed width (flex: 0 0 auto), another one no (flex: 1). The flexible children has some other children: I want this container (inner) to clip its children according to the parent width.
I managed to do this, but also I'd like to get the ellipsis overflow in case the content is clipped (the number of children is not fixed).
This is my code so far:
.outer {
border: 1px solid red;
display: flex;
width: 400px;
}
.inner {
display: flex;
min-width: 0;
overflow: hidden;
flex: 1;
text-overflow: ellipsis;
}
.child {
display: inline-block;
white-space: nowrap;
flex: 1;
border: 1px solid blue;
}
.btn {
border: 1px solid green;
flex: 0 0 auto;
}
Live here: http://jsbin.com/niheyiwiya/edit?html,css,output
How can I get the following desired result? (hacks welcome - css only please!)
There are a few problems with your layout:
text-overflow: ellipsis only works with display: block and display: inline-block containers. It's failing because you have .inner set to display: flex.
text-overflow: ellipsis must include white-space: nowrap in the same declaration. It's missing in your .inner rule.
ellipsis works on text, not block-level elements
Try this:
* {
margin: 15px 1px
}
.outer {
border: 1px solid red;
display: flex;
width: 400px;
}
.inner {
/* display: flex */ /* removed */
min-width: 0;
overflow: hidden;
flex: 1;
text-overflow: ellipsis;
white-space: nowrap; /* new */
}
.child {
display: inline; /* adjusted */
white-space: nowrap;
flex: 1;
}
.btn {
border: 1px solid green;
flex: 0 0 auto;
}
<div class="outer">
<div class="inner">
<div class="child">child 1</div>
<div class="child">child 2</div>
<div class="child">child 3</div>
<div class="child">child 4</div>
<div class="child">child 5</div>
<div class="child">child 6</div>
<div class="child">child 7</div>
</div>
<div class="btn">My big big big button!</div>
</div>
More about text-overflow: ellipsis here: Applying an ellipsis to multiline text
Here is JS approach where you could find which child div have position that overflows with position of button, and hide all divs after that div and append ... after that div.
var child = $('.child');
var btn = $('.btn');
var oW = $('.outer').innerWidth();
var w = btn.outerWidth();
var c = oW - w;
var last;
child.each(function() {
var l = $(this).position().left + $(this).outerWidth();
if (l > c) {
if (last == undefined) last = $(this).index() - 1;
}
})
$('.child:gt(' + last + ')').css('display', 'none');
$('.child:eq(' + last + ')').after(' ...')
* {
margin: 15px 1px
}
.outer {
border: 1px solid red;
display: flex;
width: 400px;
}
.inner {
overflow: hidden;
white-space: nowrap;
flex: 1;
}
.child {
border: 1px solid blue;
display: inline-block;
}
.btn {
border: 1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer">
<div class="inner">
<div class="child">child 1</div>
<div class="child">child 2</div>
<div class="child">child 3</div>
<div class="child">child 4</div>
<div class="child">child 5</div>
<div class="child">child 6</div>
<div class="child">child 7</div>
</div>
<div class="btn">My big big big button!</div>
</div>
In addition to the previous answer:
if you nest the flex-elements, than you have to add
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
to the parent container otherwise the hiding of the overflow may not work any more.
In some cases you need width: 0; in addition/instead of to min-width: 0;.
A great example with min-width: 0; which just works: https://css-tricks.com/flexbox-truncated-text/
BUT:
If your text to trancate is inside the a-tag, than you have to wrap that a-tag, in e.g. h2 or p. Otherwise the text will not be truncated because of the a-tag!
So here is the working example with the a-tag basing on example above:
.flex-parent {
display: flex;
align-items: center;
}
.long-and-truncated-with-child-corrected {
flex: 1;
min-width: 0;
/* or some value */;
}
.long-and-truncated-with-child-corrected h2 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.short-and-fixed {
white-space: nowrap;
}
.short-and-fixed > div {
width: 30px;
height: 30px;
border-radius: 10px;
background: lightgreen;
display: inline-block;
}
<div class="flex-parent">
<div class="long-and-truncated-with-child-corrected">
<h2>
333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
</h2>
</div>
<div class="long-and-truncated-with-child-corrected">
<h2>
<a href="https://vgn.de">
44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
</a>
</h2>
</div>
<div class="short-and-fixed">
<div></div>
<div></div>
<div></div>
</div>
</div>

Categories