Flexbox with collapsible elements - prevent width changes - html

I am using the disclosure elements ( and ) inside a flexbox along with another element.
Is there anyway I can force the collapsed element (i.e. the ) to take up the same width as the expanded element?
Currently, when I expand the details, the width will increase, and then decrease when I collapse it again:
This image shows the flexbox around the two elements:
I essentially want the collapsed width to be equal to the expanded width, preferably without setting any fixed widths....

Personally I feel that the best way would be to set a width on the container of the accordion. However, since you do not want to explicitly set widths, here is something you could do.
Instead of hiding your collapsible item by using display: none, use visibility: hidden instead. This will render the element invisible and you will not be able to interact with it, but it will preserve the width needed for rendering, since the element is still there. To get rid of the vertical space, set height: 0.
I've created a snippet for you to look at:
function toggle(el) {
el.children[0].classList.toggle('hide')
}
* {
font-family: sans-serif;
}
.main {
background: steelblue;
display: flex;
width: 100%;
}
.sidepanel {
background: crimson;
display: flex;
min-height: 100vh;
color: white;
padding: 20px 10px;
}
.container {
display: flex;
}
.hide {
visibility: hidden;
height: 0;
}
<div class="container">
<div class="sidepanel">
<ul onclick="toggle(this)"> Click Me!
<div class="hide">
<li>Data</li>
<li>Data</li>
<li>Data that has some words</li>
</div>
</ul>
</div>
<div class="main"></div>
</div>
There's an issue with this approach though. If you do not set a width on the left panel it might take up too much space, if the menu items do not wrap their text. And wrapping of text implies that there is some sort of defined width so...

Related

How to make 2 divs the same height

I am trying to get 2 divs that do not have a common parent div to be the height of the larger div. (using display: flex).
As shown in the above code, I would like <child-div1> and <child-div2> to have the same height. Currently, I have display: flex on the <parent-div> which successfully makes <middle-div1> and <middle-div2> to have the same height. However, I can't seem to figure out how to ensure that <child-div1> and <child-div2> have the same height.
<parent-div style="display: flex">
<middle-div1>
<child-div1></child-div1>
</middle-div1>
<middle-div2>
<child-div2></child-div2>
</middle-div2>
</parent-div>
In order to figure it out you could right click in the page, then select inspect element, and you going to see a window like this:
by clicking the most left icon and hovering over the two divs, you are going to see the exact width x height
Add display: flex to the <middle-div> flex items.
This will automatically apply align-items: stretch to the <child-div> children. (Just note that a height rule will override align-items: stretch.)
With that layout, you can set both children to have height: inherit; it's inheriting the height from the tallest part of the container. So for example, if you have an image on one side that is 400 px tall, that stretches the container, therefore, allowing the other child to grow in height also.
.container {
display: flex;
}
.one, .two {
height: inherit;
width: 50%;
}
.one {
background-color: lightblue;
}
.two {
background-color: darkgreen;
color: white;
}
<div class="container">
<div class="one">1<br><img src="https://dummyimage.com/400x400/000/fff&text=test"></div>
<div class="two">2</div>
</div>
One solution is to add height:100%; to child-div1 and child-div2
<parent-div style = "display: flex">
<middle-div1>
<child-div1 style="height: 100%;"></child-div1>
</middle-div1>
<middle-div2>
<child-div2 style="height: 100%;"></child-div2>
</middle-div2>
</parent-div>

Horizontal scroll not working on a div element

#Here, I'm trying to create horizontal scrolling for a div element for my application. The div element consists of ul li element and some other div tags for my requirement. The Ul li elements are dynamically added inside the parent div element.
Although I could get the vertical scrolling working properly and my horizontal scrolling is displayed using overflow-x: scroll. I am not able to scroll it, the ul li elements gets distorted. I have set a predefined width of 700px for the div container also. Its like the horizontal scrolling is disabled. I am not using overflow anywhere else in the application
<div class="org-chart" appOrgachart [empArr]="employees" [orgaArr]="orgaArr" *ngIf="employees.length>0 && !isLoading">
<ul>
<li *ngFor="let emp of empArr">
<div class="user">
<div class="name">{{emp.empname}}</div>
<div class="role">{{emp.empdesgname}}</div>
</div>
</li>
</ul>
</div>
My CSS file:
.org-chart {
display: flex;
justify-content: center;
left: 29px;
position: relative;
overflow-x: scroll !important;
overflow-y: scroll;
height: 400px;
width: 65%;
transform: translateY(12%);
}
Looking at your code, providing overflow-x: scroll !important; is big no no from me, it should be the last option for you to use.
now coming to your requirement, you need to specifically provide overflow-x: scroll if you give overflow:auto it automatically gives you a scroll when needed.
now when is it??
when the height and width is more than the browser size that is when you will get the scrolling feature.
if you need a scroll within browser size then, decrease the width of the container and apply overflow:auto; that should give you a scroll on sight.
here is the example of what I am saying:
so what does it mean is when you want a scroll within the browser then you should have a child class and the width of that class should be less w.r.t the content so that it can overflow.
.org-chart {
display: flex;
justify-content: center;
left: 29px;
position: relative;
overflow: auto;
border: 1px solid black;
/*Main container */
height: 300px;
width: 65%;
}
.content {
width: 100%;
/* you should have another width inside main container */
border: 1px solid red;
}
<div class="org-chart" appOrgachart [empArr]="employees" [orgaArr]="orgaArr" *ngIf="employees.length>0 && !isLoading">
<ul>
<li *ngFor="let emp of empArr">
<div class="user">
<div class="name">{{emp.empname}}</div>
<div class="role">{{emp.empdesgname}}</div>
<div class="content">Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last
on only the last paragraph in the container, you can use :last child, see example below. Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it,
text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last on only the last paragraph in the container, you can use :last child, see example below. Notice that the text-align-last property sets the alignment
for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH of the paragraphs. To use text-align-last on only the last paragraph in the container, you can
use :last child, see example below. Notice that the text-align-last property sets the alignment for all last lines within the selected element. So, if you have a with three paragraphs in it, text-align-last will apply to the last line of EACH
of the paragraphs. To use text-align-last on only the last paragraph in the container, you can use :last child, see example below.</div>
</div>
</li>
</ul>
</div>
apply max-width property as 64% and overflow:auto

Horizontal List of 2 items with second fixed width and first fill-width

ul.horiz {
margin: 0;
padding: 0;
list-style-type: none;
}
ul.horiz > li {
display: inline;
}
<ul class="horiz">
<li>This is the first item text</li>
<li>X</li>
</ul>
I want to have a horizontal list of two items fit in a div 100% of the div (so it adjusts as the browser (and div) changes width. The second list item should have a fixed width and the first item should fill the remaining space.
I'm not sure how this is possible. I don't want to do percentages, if possible.
It doesn't necessarily have to be a list (i.e. ul/li), but that was my initial thought.
The first item would be text content and the second item would be an image.
Check out this fiddle I've put together: http://jsfiddle.net/xvo2682e/
It uses the following HTML/CSS:
.main
{
width: 100%;
overflow: auto;
}
.scaling_left
{
margin-right: 100px;
background-color: #D9F2D0;
}
.fixed_right
{
float:right;
width: 100px;
background-color: #efefef;
}
<div class="main">
<div class="fixed_right">
Right Column is skinny.
</div>
<div class="scaling_left">
Left column is variably fat.
</div>
</div>
Basically, don't float the div whose width you want to scale with the page. Then give that scaling div a margin equal to the width of the fixed-width div on the same side that you float it to.
[Display table approche][1]
If I understand what you are asking for correctly, this might be one of the way [1]: http://jsbin.com/tonovupite/1/edit?html,css,output

Avoid right-floated DIV wrapping without adding any height in container

I'm trying to have a toolbar always aligned to the right within a DIV without adding any height. The problem I'm finding is making this work both when the box has 100% width and when the width is determined by content. The HTML looks something similar to this:
<div class="box">
<div class="title">
float right
</div>
<div class="toolbar">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
</div>
</div>
I managed to make it work in Firefox, but Chrome wraps the toolbar when there is not enough space for it instead of increasing the width of the container.
.box {
border: 1px solid #ccc;
display: inline-block;
margin: 5px 0 15px;
}
.title {
display: inline-block;
}
.toolbar {
background: #eee;
float: right;
margin-left: 25px;
}
I would like to find a single set of rules to achieve this regardless the width of the container, but I'm out of ideas unless I use some extra class to differentiate both cases. Also, I'm trying to avoid using overflow or clearfix because I don't want the toolbar to affect the height of the box.
In this fiddle I show all combinations I have tried: http://jsfiddle.net/omegak/c4y4t/2/
You can try this, This worked for me.
.title {
float:left;
}
See if this is the desired output
Updated the below css and added clearfix class to the parent div
.title {
float:left;
}
Add the following CSS and clear the floats on first Div.
.title {
float:left;
}
Here is the demo
I got it working in the end with a little hack.
I gave up on trying the title not to be float: left. Then, to prevent the box to have no height I added overflow: hidden to it. Finally, the hack consists on setting margin-bottom: -999px on the toolbar to prevent it from adding any extra height to the box.
Here is the solution: http://jsfiddle.net/c4y4t/8/

How can I expand floated child div's height to parent's height?

I have the page structure as:
<div class="parent">
<div class="child-left floatLeft">
</div>
<div class="child-right floatLeft">
</div>
</div>
Now, the child-left DIV will have more content, so the parent DIV's height increases as per the child DIV.
But the problem is child-right height is not increasing. How can I make its height as equal to it's parent?
For the parent element, add the following properties:
.parent {
overflow: hidden;
position: relative;
width: 100%;
}
then for .child-right these:
.child-right {
background:green;
height: 100%;
width: 50%;
position: absolute;
right: 0;
top: 0;
}
Find more detailed results with CSS examples here and more information about equal height columns here.
A common solution to this problem uses absolute positioning or cropped floats, but these are tricky in that they require extensive tuning if your columns change in number+size, and that you need to make sure your "main" column is always the longest. Instead, I'd suggest you use one of three more robust solutions:
display: flex: by far the simplest & best solution and very flexible - but unsupported by IE9 and older.
table or display: table: very simple, very compatible (pretty much every browser ever), quite flexible.
display: inline-block; width:50% with a negative margin hack: quite simple, but column-bottom borders are a little tricky.
1. display:flex
This is really simple, and it's easy to adapt to more complex or more detailed layouts - but flexbox is only supported by IE10 or later (in addition to other modern browsers).
Example: http://output.jsbin.com/hetunujuma/1
Relevant html:
<div class="parent"><div>column 1</div><div>column 2</div></div>
Relevant css:
.parent { display: -ms-flex; display: -webkit-flex; display: flex; }
.parent>div { flex:1; }
Flexbox has support for a lot more options, but to simply have any number of columns the above suffices!
2.<table> or display: table
A simple & extremely compatible way to do this is to use a table - I'd recommend you try that first if you need old-IE support. You're dealing with columns; divs + floats simply aren't the best way to do that (not to mention the fact that multiple levels of nested divs just to hack around css limitations is hardly more "semantic" than just using a simple table). If you do not wish to use the table element, consider css display: table (unsupported by IE7 and older).
Example: http://jsfiddle.net/emn13/7FFp3/
Relevant html: (but consider using a plain <table> instead)
<div class="parent"><div>column 1</div><div>column 2</div></div>
Relevant css:
.parent { display: table; }
.parent > div {display: table-cell; width:50%; }
/*omit width:50% for auto-scaled column widths*/
This approach is far more robust than using overflow:hidden with floats. You can add pretty much any number of columns; you can have them auto-scale if you want; and you retain compatibility with ancient browsers. Unlike the float solution requires, you also don't need to know beforehand which column is longest; the height scales just fine.
KISS: don't use float hacks unless you specifically need to. If IE7 is an issue, I'd still pick a plain table with semantic columns over a hard-to-maintain, less flexible trick-CSS solution any day.
By the way, if you need your layout to be responsive (e.g. no columns on small mobile phones) you can use a #media query to fall back to plain block layout for small screen widths - this works whether you use <table> or any other display: table element.
3. display:inline block with a negative margin hack.
Another alternative is to use display:inline block.
Example: http://jsbin.com/ovuqes/2/edit
Relevant html: (the absence of spaces between the div tags is significant!)
<div class="parent"><div><div>column 1</div></div><div><div>column 2</div></div></div>
Relevant css:
.parent {
position: relative; width: 100%; white-space: nowrap; overflow: hidden;
}
.parent>div {
display:inline-block; width:50%; white-space:normal; vertical-align:top;
}
.parent>div>div {
padding-bottom: 32768px; margin-bottom: -32768px;
}
This is slightly tricky, and the negative margin means that the "true" bottom of the columns is obscured. This in turn means you can't position anything relative to the bottom of those columns because that's cut off by overflow: hidden. Note that in addition to inline-blocks, you can achieve a similar effect with floats.
TL;DR: use flexbox if you can ignore IE9 and older; otherwise try a (css) table. If neither of those options work for you, there are negative margin hacks, but these can cause weird display issues that are easy to miss during development, and there are layout limitations you need to be aware of.
For the parent:
display: flex;
For children:
align-items: stretch;
You should add some prefixes, check caniuse.
I found a lot of answers, but probably the best solution for me is
.parent {
overflow: hidden;
}
.parent .floatLeft {
# your other styles
float: left;
margin-bottom: -99999px;
padding-bottom: 99999px;
}
You can check other solutions here http://css-tricks.com/fluid-width-equal-height-columns/
Please set parent div to overflow: hidden
then in child divs you can set a large amount for padding-bottom. for example
padding-bottom: 5000px
then margin-bottom: -5000px
and then all child divs will be the height of the parent.
Of course this wont work if you are trying to put content in the parent div (outside of other divs that is)
.parent{
border: 1px solid black;
overflow: hidden;
height: auto;
}
.child{
float: left;
padding-bottom: 1500px;
margin-bottom: -1500px;
}
.child1{
background: red;
padding-right: 10px;
}
.child2{
background: green;
padding-left: 10px;
}
<div class="parent">
<div class="child1 child">
One line text in child1
</div>
<div class="child2 child">
Three line text in child2<br />
Three line text in child2<br />
Three line text in child2
</div>
</div>
Example: http://jsfiddle.net/Tareqdhk/DAFEC/
Does the parent have a height? If you set the parents height like so.
div.parent { height: 300px };
Then you can make the child stretch to the full height like this.
div.child-right { height: 100% };
EDIT
Here is how you would do it using JavaScript.
CSS table display is ideal for this:
.parent {
display: table;
width: 100%;
}
.parent > div {
display: table-cell;
}
.child-left {
background: powderblue;
}
.child-right {
background: papayawhip;
}
<div class="parent">
<div class="child-left">Short</div>
<div class="child-right">Tall<br>Tall</div>
</div>
Original answer (assumed any column could be taller):
You're trying to make the parent's height dependent on the children's height and children's height dependent on parent's height. Won't compute. CSS Faux columns is the best solution. There's more than one way of doing that. I'd rather not use JavaScript.
I used this for a comment section:
.parent {
display: flex;
float: left;
border-top:2px solid black;
width:635px;
margin:10px 0px 0px 0px;
padding:0px 20px 0px 20px;
background-color: rgba(255,255,255,0.5);
}
.child-left {
align-items: stretch;
float: left;
width:135px;
padding:10px 10px 10px 0px;
height:inherit;
border-right:2px solid black;
}
.child-right {
align-items: stretch;
float: left;
width:468px;
padding:10px;
}
<div class="parent">
<div class="child-left">Short</div>
<div class="child-right">Tall<br>Tall</div>
</div>
You could float the child-right to the right, but in this case I've calculated the widths of each div precisely.
I have recently done this on my website using jQuery. The code calculates the height of the tallest div and sets the other divs to the same height. Here's the technique:
http://www.broken-links.com/2009/01/20/very-quick-equal-height-columns-in-jquery/
I don't believe height:100% will work, so if you don't explicitly know the div heights I don't think there is a pure CSS solution.
If you are aware of bootstrap you can do it easily by using 'flex' property.All you need to do is pass below css properties to parent div
.homepageSection {
overflow: hidden;
height: auto;
display: flex;
flex-flow: row;
}
where .homepageSection is my parent div.
Now add child div in your html as
<div class="abc col-md-6">
<div class="abc col-md-6">
where abc is my child div.You can check equality of height in both child div irrespective of border just by giving border to child div
<div class="parent" style="height:500px;">
<div class="child-left floatLeft" style="height:100%">
</div>
<div class="child-right floatLeft" style="height:100%">
</div>
</div>
I used inline style just to give idea.
I can see that the accepted answer uses position: absolute; instead of float: left. In case you want to use float: left with the following structure,
<div class="parent">
<div class="child-left floatLeft"></div>
<div class="child-right floatLeft"></div>
</div>
Give position: auto; to the parent so that it will contain its children height.
.parent {
position: auto;
}
.floatLeft {
float: left
}
I learned of this neat trick in an internship interview. The original question is how do you ensure the height of each top component in three columns have the same height that shows all the content available. Basically create a child component that is invisible that renders the maximum possible height.
<div class="parent">
<div class="assert-height invisible">
<!-- content -->
</div>
<div class="shown">
<!-- content -->
</div>
</div>