Stretch elements to the height of their container using CSS only - css

Concider the following fiddle: http://jsfiddle.net/dts2T/
This has been bugging me for quite some time now. The Javascript in this fiddle should be redundant. But I've ripped my hair out googling this: How can I do the same using ONLY CSS?
The problem lies in the fact that any of the three columns could potentially contain more than one child. First I need to stretch each .column container to the height of the #bottom div. Then I need to stretch the height of the last element in each .column, so that it fills the remaining space of it's container. But HOW?
And before any of you suggests Faux columns or any other crappy solution to fake column stretching, thank you, but such solutions won't apply to this problem at all. The design I'm implementing suggests gradients on columns and rounded corners, which will make faux columns not applicable. It is the easiest thing in the world to stretch things horizontally, why can' it be equally easy to stretch them vertically?! Aargh!!
I would really appreciate any help from you brilliant guys out there. Any suggestion would be fine. I would even appreciate a good discussion on faking vertical stretching, if it is constructive.
Thank you.

This is a headbanging issue a lot of people run into at one time or another.
You can set the section to display: table; and columns to display: table-cell;. Even border radius and whatever fancy stuff works on it.
Here is a working demo: http://jsfiddle.net/MadLittleMods/QykYu/
Also here is the HTML and CSS:
CSS:
.container
{
display: table;
width: 100%;
border: 2px solid #000000;
}
.column
{
display: table-cell;
border: 1px solid #ff0000;
border-radius: 10px;
}
HTML:
<section class="container">
<div class="column">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
<div class="column">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
</ul>
</div>
<div class="column">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
</ul>
</div>
</section>
​
​

Related

CSS Selector for last-of-type/last-child but different parents? [duplicate]

This question already has an answer here:
Select :last-child with especific class name (with only css)
(1 answer)
Closed 2 years ago.
Would like to access item 6 only through css
<div class="div-class">
<li class="li-class">Item 1</li>
<li class="li-class">Item 2</li>
<li class="li-class">Item 3</li>
</div>
<div class="div-class">
<li class="li-class">Item 4</li>
<li class="li-class">Item 5</li>
<li class="li-class">Item 6</li>
</div>
EDIT
I think that it is duplicate. Select :last-child with especific class name (with only css)
So you need which div you want to point. In this case, this is second div so we specified:
div:nth-child(2)
And then we just select last li as below:
li:last-child
So finaly we got:
div:nth-child(2) li:last-child{
background-color: red;
}
EDIT
With jQuery:
$('li').last().css('background', 'red');
Just to let you know, your html structure is incorrect as you should set li right after ul or ol
$('li').last().css('background', 'red');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</div>
<div>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</div>

How to setup nth-of-type() to dynamically select elements in a certain order

I need to select elements in a certain order. I have an image carousel that could have any number of images but only 3 images show at a time. I need to add css styles to the 1st and 3rd image and different styles to the 2nd image.
The code below is a simplified version of what I am looking for. I need it to be dynamic as I dont know the number images the carousel will have. Is there a formula for example nth-of-type(4n-7), that I can use to target this order dynamically?
li:nth-of-type(1),
li:nth-of-type(3),
li:nth-of-type(4),
li:nth-of-type(6),
li:nth-of-type(7),
li:nth-of-type(9) {
color: red;
}
li:nth-of-type(2),
li:nth-of-type(5),
li:nth-of-type(8) {
color: blue;
}
From your text you want to select every third image/item starting with the 2nd one.
If so the selector would be element:nth-of-type(3n+2)
li:nth-of-type(3n+2) {
color: red;
}
li:nth-of-type(3n) { /* for demo only */
margin-bottom: 1em;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
</ul>

How can I arrange a series of lists so they stack on top of each other?

This is what I have:
And this is what I want:
I cannot easily change the DOM structure as I am working with a WordPress list generated via creating a new menu. I have tried different techniques such as Flexbox and grid but I just cannot seem to get the results I am after. I'd love it if someone could help here. Thank you.
https://codepen.io/WayneHaworth/pen/BGzzpr
<div class="container">
<ul id="main-menu">
<li>
<span>List 1</span>
<ul class="inner-list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
</ul>
</li>
<li>
<span>List 2</span>
<ul class="inner-list">
<li>item 1</li>
<li>item 2</li>
</ul>
</li>
...etc
</ul>
</div>
As per #Doug's comment, adding a CSS column to the outside UL fixed this.
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 5;

How can I create multi columns from a single unordered list?

I'd like to create a multi column list like this:
https://jsfiddle.net/37dfwf4u/
No problem when using a different list for each column:
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
</ul>
<ul>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
</ul>
ul {
display:inline-block;
}
However, can this be done by a continuous list and pure CSS so that the CSS arranges the columns automatically?
E.g. by use of flex layout which I'm not yet familiar with?
Yes, you can create a multi column list as described if you make the ul a flex container, change the flex-direction to column, allow it to wrap by applying flex-wrap: wrap and additionally force it to wrap by limiting its height:
ul {
height: 100px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
<li>item 9</li>
<li>item 10</li>
<li>item 11</li>
<li>item 12</li>
<li>item 13</li>
<li>item 14</li>
<li>item 15</li>
<li>item 16</li>
<li>item 17</li>
<li>item 18 </li>
<li>item 19</li>
<li>item 20</li>
<li>item 21</li>
</ul>
Here's another possibility, added half a year later after the comment by #Andrew Koper:
You can also use the colummn-count parameter, which doesn't require a fixed height (and also not flex), but defines a fixed number of columns. So in the example below, even just two list items would be broken into two columns of one list item each:
ul {
column-count: 2;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
<li>item 9</li>
<li>item 10</li>
<li>item 11</li>
<li>item 12</li>
<li>item 13</li>
<li>item 14</li>
<li>item 15</li>
<li>item 16</li>
<li>item 17</li>
<li>item 18 </li>
<li>item 19</li>
<li>item 20</li>
<li>item 21</li>
</ul>
Consider using CSS3 Multi-column Layout for that:
CSS3 Multiple Columns
You can do that using just one list and define the number of columns with CSS. If you check CSS3 Multi-column layout browser support here you can see partial support by most of the browsers, because they do not support break-before, break-after and break-inside properties. But they do support the properties you will need to create a multi column list with a prefix.
.container {
-webkit-column-count: 2; /* Chrome, Safari, Opera */
-moz-column-count: 2; /* Firefox */
column-count: 2;
}
ul {
margin: 0;
}
<div class="container">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
</ul>
</div>

Why doesn't overflow-y:visible look the same as overflow:visible

This is a mock up of a menu i have
HTML
Menu 1 (overflow:hidden)
<div class='menu'>
<ul>
<li>
Item 1
<ul>
<li>submenu 1</li>
<li>submenu 2</li>
<li>submenu 3</li>
<li>submenu 4</li>
<li>submenu 5</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
<br/><br/>
Menu 2 (overflow:hidden; overflow-y visible)
<div class='menu menu2'>
<ul>
<li>
Item 1
<ul>
<li>submenu 1</li>
<li>submenu 2</li>
<li>submenu 3</li>
<li>submenu 4</li>
<li>submenu 5</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
<br/><br/>
Menu 3 (overflow-x:hidden;)
<div class='menu3'>
<ul>
<li>
Item 1
<ul>
<li>submenu 1</li>
<li>submenu 2</li>
<li>submenu 3</li>
<li>submenu 4</li>
<li>submenu 5</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
<br/><br/>
Menu 4 (overflow:visible;)
<div class='menu menu4'>
<ul>
<li>
Item 1
<ul>
<li>submenu 1</li>
<li>submenu 2</li>
<li>submenu 3</li>
<li>submenu 4</li>
<li>submenu 5</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
CSS
.menu {border:1px solid #000000; overflow:hidden;}
.menu ul {list-style:none; margin:5px 5px; padding:0; position:relative}
.menu li {display:inline-block}
.menu li::after {content: " | ";}
.menu ul ul {position:absolute}
.menu ul ul li {display:block;}
.menu2 {overflow-y:visible}
.menu4 {overflow:visible}
.menu3 {border:1px solid #FF0000;overflow-x:hidden}
.menu3 ul {list-style:none; margin:5px 5px; padding:0; position:relative}
.menu3 li {display:inline-block}
.menu3 li::after {content: " | ";}
.menu3 ul ul {position:absolute}
.menu3 ul ul li {display:block;}
Fiddle
Now the idea is that menu item 1 has a sub menu which is triggered to appear via javascript and the submenu is supposed to go outside the box. because this menu is supposed to be responsive i assume the overflow was set in the template for a reason and i want to avoid altering the template as much as i can.
Now as you can see with the code the submenu in Menu 1 is hidden in the box, when i go to override the overflow-y property in Menu 2 to be it's default value (which is the same as overflow's) it's still hidden and there's a scroll box.
now just in case if there was something weird in overflow is still set for the y axis i went and copied the menu class for Menu 3 but instead of doing overflow:hidden i just did overflow-x:hidden; but that still have be a scrollbar. Menu 4 shows how if overflow is set to visible (the default value) i have no scroll bar and my submenu goes out of the box as it should.
My question is why doesn't overflow-y:visible look the same as overflow:visible? to my understanding, overflow:visible is just overflow-x:visible; overflow-y:visible much like how border:1px solid #000000 is the same as setting all the border sides's width, style and color one by one
overflow-x and overflow-y are part of CSS3 (while plain overflow is CSS2), and are still somewhat experimental. The rules for what happens when one value is a "scrolling value" (which includes hidden) and the other is visible are complex, and frankly confusing.
From the CSS3 Overflow Spec:
... if one cascaded values [sic] is one of the scrolling values and the other is ‘visible’, then computed values are the cascaded values with ‘visible’ changed to ‘hidden’.
This seems to justify the behavior you're seeing, but I don't understand why it was designed that way.
overflow: visible;
does not clip content and can be shown out side of content box but for
overflow-y; visible;
content clipped against content box with overflow auto default
I made a revised fiddle but the main issue I found is that the style for .menu was applied to all four menus and that part of its definition was overflow: hiddden, so you were basically getting a conflict with Menu 2. Deleting overflow: hidden from .menu in the first line of your CSS makes both Menu 2 and Menu 4 have the same behavior as you were expecting.

Resources