Is there a way to determine layouts with css/html based on the specific child amounts?
See below for a layout example.
I've attempted to get it to work with nth-child, but I may be doing this incorrectly..
https://codepen.io/brycesnyder/pen/EvBzWq
But I'm not sure if there is a way to make all elements span 50% width, and if there are more than 1 the following should stack.
/* three items */
li:first-child:nth-last-child(3):not(:first-child),
li:first-child:nth-last-child(3) ~ li {
background: green;
}
EDIT: I know this is possible via standard elements like so: https://codepen.io/brycesnyder/pen/GvbbyY I want to be able to use just a UL > LI
So... it's not exactly "based on the number of children", but you can achieve the layout you're looking for by changing your flex direction to column, setting width to 50%, and having the first element have flex; 0 0 100%. You'll also need to set the special case of a 1 child list (:first-child:nth-last-child(1)) to be width 100%.
The key css ends up looking like this:
ul {
padding:10px 1px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
list-style-type: none;
}
li {
outline:1px solid gray;
text-align:center;
width: 50%;
margin: 0;
padding: 0;
flex: 1 1 auto;
}
li:first-child {
height: 100%;
flex: 0 0 100%;
}
/* one item */
li:first-child:nth-last-child(1) {
width: 100%;
}
Here's a codepen I set up forked from yours:
https://codepen.io/kball/pen/yomyyg
Related
I have a block with a fixed width and a max height size. I need to place into this block two elements: a list and a dynamic size image.
They are have to be at one level like a columns in a table. The list have to be a 20% width of the main block, and image - 80% width.
The image would change its size when the windows width would decrease.
And I need that the list fills whole row height preserving the equal height for each list item.
Can I achieve that only with a help of CSS? Also I don't want to use display: grid and display: flex to resolve browser compatibility issue.
Also discarding ui li in favor of representing each list item as a simple div is impossible or too complicated solution in that case.
If it is only possible with the help of grid or flex then I will appreciate such solution in any case.
An example:
https://jsfiddle.net/Eugenii10/y0otpo2e/2/
What I want to get:
https://i.imgur.com/CL3m3Df.jpg
Thanks in advance!
This can be accomplished with flex-box
DEMO
#wrapper {
border: 1px solid black;
display: flex;
}
#firstCol { width: 28%; }
#firstCol ul {
margin: 0px;
padding: 0px;
list-style-type: none;
height: 100%;
flex-direction: column;
display: flex;
}
#firstCol ul > li {
display: flex;
flex-grow: 1;
}
#firstCol ul > li > a {
border: 1px solid rgb(0, 0, 0);
text-align: center;
flex-grow: 1;
padding: 1rem 0;
}
#secondCol {}
#secondCol img {
max-width: 100%;
max-height: 300px;
}
I have 3 elements in HTML as follows:
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>
This should fit in the 100% width of the container (<body> or any other <div>). However the .sidebar is being dropped to the next line. I tried to setup border, margin and padding to 0 with the !important definition (just to test) but the result is the same. How can I fit this 3 elements in the same line keeping the width property?
Thanks in advance for your answers.
As someone else mentioned, the issue is that when using display: inline-block, white-space - even between element tags - is accounted for in rendering. There are a few ways to get around this.
Setting display: table-cell rather than inline-block can work in a simple situation like this; just note that it prevents the blocks from wrapping
You can set font-size:0; on the parent to get rid of the whitespace, but you'll have to reset it on all the direct children.
Unless you have to support pre-IE10 browsers, I'd recommend flexbox here! You may need to add some browser prefixes, but the base would look like this (name your parent element something better than 'parent', though!):
.parent { display: flex; }
.navigation, .sidebar { flex: 1 }
.content { flex: 2 }
What that snippet is saying is "make the children fit, and make .content twice as big as the other two".
Even though you removed the padding, margin, and border, inline elements are actually sensitive to white space in the code itself. Remove that and they line up:
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
* {
margin: 0;
padding: 0;
border: 0;
}
<nav class="navigation">Navigation</nav><section class="content">Section</section><aside class="sidebar">Aside</aside>
When you're using display inline-block, it takes the space in your code as a character(space), so, you have 100% + the space required for 2 characters, you could keep the formatting of your code and ¨remove¨ the space between your containers setting the font-size of the parent to 0
.container{
font-size:0;
}
.container *{
font-size:12px;
}
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<div class="container">
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>
</div>
It's because you're using the style of display:inline-block which will recognize and create a space between element if your code have a space (either space, or new line), so what you need to do is just remove the space like answered by j08691 here
Or you can either remove the spacing by using a comment like this one
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<nav class="navigation">Navigation</nav><!--
--><section class="content">Section</section><!--
--><aside class="sidebar">Aside</aside>
Or other way around is using the style margin like in this example, the background is used to visualize the size of the the inline-block element only
.navigation {
display: inline-block;
width: 25%;
margin: 0 -0.4em 0 0; background: red;
}
.content {
display: inline-block;
width: 50%;
margin: 0 -0.4em 0 0; background: green;
}
.sidebar {
display: inline-block;
width: 25%;
margin: 0 -0.4em 0 0; background: blue;
}
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>
Can i get the height of the previous element using only CSS?
I am using calc() function to set dynamically height of the div B.
#b{
height:calc(100vh - heightOfPreviousElement);
}
I need to know the height of the previous element.
what i know is that, 100vh is equal to 100% of the screen height.
I used the code in the answer below.Using flex,
I have one problem. The height of the color orange become smaller.
You can easily achieve the effect you're looking for using flexbox. The trick is to allow the blue container (the one with the flexible height) to grow in size whenever the need arises, using flex: 1 1 auto, which is simply a shorthand for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
See proof-of-concept code snippet below:
body {
padding: 0;
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: no-wrap;
align-items: center;
justify-content: center;
height: 100vh;
}
.wrapper > div {
width: 100%;
}
#c1 {
background-color: #880015;
color: #fff;
height: 60px;
margin-bottom: 10px;
}
#c2 {
background-color: #ff7f27;
}
#c3 {
background-color: #00a2e8;
flex: 1 1 auto;
margin-bottom: 10px;
}
<div class="wrapper">
<div id="c1">height: 60px</div>
<div id="c2">height: auto (determined by content?)</div>
<div id="c3">flexible height</div>
</div>
No you can't select a previous element in CSS.
You might be interested in JQuery Prev OR Parents method for selecting previous element and apply height using .css() method?
I'm trying to get some list items to stretch across a list
This is the relevant code
#navbar ul
{
list-style-type: none;
margin: 0;
padding: 0;
width: 100%;
}
#navbar li
{
display: inline;
float: left;
width: 33.33%;
}
Here's what it normally looks like:
But sometimes when I leave the page and come back later (not after reloading) this happens:
Setting the individual item width to 33.3% makes it one pixel short and making it 33.333% makes the problem worse...
You could easily achieve this layout using css tables instead. Widely supported and semantically sound.
#navbar ul {
width: 100%;
display: table;
table-layout: fixed; /* makes all cells equal width */
}
#navbar li {
display: table-cell;
}
http://jsfiddle.net/kBnrz/1/
remove padding of parent of "ul"
Just fake it:
#navbar ul li{
width:33%;
}
#navbar ul li:last-child{
width:34%;
}
Also include this style:
* { box-sizing: border-box }
ref: http://www.paulirish.com/2012/box-sizing-border-box-ftw/
Suggestion:
#Miro try CSS Flexbox layout, it will help you, but it works only in modern browsers.
CSS Flexbox
The CSS Flexible Box Layout Model, or "flexbox", is one of the specification in CSS3. It provides for the arrangement of elements on a page such that the elements behave predictably when the page layout must accommodate different screen sizes and different display devices. For many applications, the flexible box model provides an improvement over the block model in that it does not use floats, nor do the flex container's margins collapse with the margins of its contents.
Here is one example
Html
<div class="box">
<div class="A">A</div>
<div class="B">B</div>
<div class="C">C</div>
</div>
StyleSheet
html, body{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.box {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-content: center;
align-items: flex-start;
}
.box div.A {
order:1;
flex: 1 1 auto;
align-self: auto;
min-width: 0;
min-height: auto;
}
.box div.B {
order:2;
flex: 1 1 auto;
align-self: auto;
min-width: 0;
min-height: auto;
}
.box div.C {
order:2;
flex: 1 1 auto;
align-self: auto;
min-width: 0;
min-height: auto;
}
Here is the Demo
This Link will help you.
I'm playing with css3's flexbox in Chrome (no need to worry about cross-browser for this). I'm having a hard time convincing it to lay out my content the way I'd like. Here's a sketch of my goal:
Here's a jsFiddle of my attempt: http://jsfiddle.net/Yht4V/2/ This seems to work great except each .group will expand its height rather than create multiple columns.
I'm using flexbox pervasively here. The body lays out vertically, with the #content div taking the remaining height of the page. Each .group is laid out horizontally. Finally, each .item is laid out within a .group vertically with wrapping.
Unfortunately, each .group ends up as a single column by expanding the #content height, which causes a vertical scrollbar (unwanted). If I set the height of each .group to a fixed pixel size, the items break out into multiple columns, but this defeats the fluidity of the flexbox. Here's what it looks like with fixed heights: http://jsfiddle.net/Yht4V/3/
So, how can I get my #content div to not expand vertically since everything is managed with flexboxes without setting a fixed height? I was expecting the flexbox to trigger more columns instead of expanding the height of its parent and causing a scrollbar.
From what I've seen with the Chrome and Opera implementations for Flexbox, a flex-direction of column requires restricting the height of the element, otherwise it will continue expanding vertically. It doesn't have to be a fixed value, it can be a percentage.
That said, the layout you want for your .group elements can also be achieved by using the CSS Columns module. The flow of the elements will be similar to that of the flexbox column orientation, but it will create columns as long as there's enough width for them, regardless of how long the document is.
http://jsfiddle.net/Yht4V/8/ (you'll have to excuse the lack of prefixes)
html {
height: 100%;
}
body {
height: 100%;
display: flex;
flex-flow: column nowrap;
}
h1 {
padding: 1em;
}
#content {
padding: 10px;
background-color: #eee;
display: flex;
flex-grow: 1;
}
#content > .group {
margin: 10px;
padding: 10px;
border: 1px solid #cfcfcf;
background-color: #ddd;
flex: 1 1 auto;
}
#content > .group:first-child {
columns: 10em;
flex-grow: 2;
}
#content > .group .item {
margin: 10px;
padding: 10px;
background-color: #aaa;
break-inside: avoid;
}
#content > .group .item:first-child {
margin-top: 0;
}
Leaving it as a bunch of nested flexboxes, this was about as close as I could get it:
http://jsfiddle.net/Yht4V/9/ (again, no prefixes)
html {
height: 100%;
}
body {
height: 100%;
display: flex;
flex-flow: column nowrap;
}
h1 {
padding: 1em;
}
#content {
padding: 10px;
background-color: #eee;
display: flex;
flex: 1 1 auto;
height: 100%;
width: 100%;
}
#content > .group {
margin: 10px;
padding: 10px;
border: 1px solid #cfcfcf;
background-color: #ddd;
display: flex;
flex-flow: column wrap;
flex: 1 1 30%;
max-height: 100%;
}
#content > .group .item {
margin: 10px;
padding: 10px;
background-color: #aaa;
}
Replace the following in your css -
display: -webkit-flex;
to the following -
display: -webkit-box;
This worked very well for me :-)