Grid with irregular item sizes and pinned elements - html

I have to make a tag cloud. It should be looking like it shown in the picture below:
The red box here is the "show more" button which should be always sticked to the top right corner. Amount of tags (the tags are blue boxes here) is unknown, so as amount of rows.
I tried to do it with grid, but it seems it's impossible to make a non-rectangular cell. I tried to make the wrapper for blue boxes by the shape attribute, but it seems it's not an option as well.

Don't use grid for that because you don't really want a grid. Instead try flex with row-reverse - it will work if you don't care about the order of the tags (because they will be sorted in reversed horizontal order).
ul {
list-style:none;
}
li {
display: inline-block;
padding: 3px 10px;
}
.show-more,
.tag {
flex-basis: auto;
flex-grow: 1;
margin: 0 10px 10px;
text-align: center;
}
.show-more {
background-color: tomato;
color: white;
}
.tag {
background-color: beige;
color: black;
}
.tag:nth-child(2) { width: 100px; }
.tag:nth-child(4) { width: 120px; }
.tag:nth-child(6) { width: 75px; }
.container {
max-width: 400px;
}
.tag-list {
display: flex;
flex-flow: row-reverse wrap;
justify-content: space-between;
}
<div class="container">
<ul class="tag-list">
<li class="show-more">Show more</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
<li class="tag">...</li>
</ul>
</div>

Related

How do I center a UL/LI in the same row as left-aligned text?

I've been trying to write a menubar that has two groupings in the same row across the top of a webpage: on the left is the site name and in the center should be the menu options (a ul/li). So far, following similar issues, I've written the following, which appears on first glance to do exactly what I'm seeking.
HTML:
<div class="menubar">
SITE NAME
<ul class="ul">
<li>MENU 0</li>
<li>MENU 1</li>
<li>MENU 2</li>
<li>MENU 3</li>
</ul>
</div>
CSS:
.menubar {
width: 100%;
height: 50px;
line-height: 50px;
vertical-align: middle;
background-color: #fff;
border-bottom: 1px solid #f5f5f5;
position: fixed;
top: 0;
display: flex;
flex-flow: row nowrap;
}
.logo {
width: 33.33%;
float: left;
margin-left: 20px;
font-size: 24px;
}
.ul {
font-size: 18px;
list-style: none;
padding: 0;
margin: 0;
}
.ul li {
margin-left: 15px;
margin-right: 15px;
display: inline-block;
}
However, if you look carefully in the JSFiddle (more apparent when widening browser windows or shrinking the window down just before the items begin wrapping), the 'centered' ul/li is not actually centered—it's closer to the left side of the browser window than the right. How do I fix this so that the ul/li remains truly centered in the menubar (as if the site name doesn't exist) with the left-aligned site name, regardless of what the browser window's width is? (I'm assuming within non-wrapping reason, since I plan to adjust sizes and behavior for smaller devices.)
JSFiddle
You're using a lot of margins, width and stuff. Check out flex here and you can get the same thing, properly aligned using flex and directions.
<!-- NEW CODE -->
<nav>
<div class="logo">
<span>Your Company</span>
</div>
<ul class="nav-items">
<li class="nav-item"> Menu 1 </li>
<li class="nav-item"> Menu 2 </li>
<li class="nav-item"> Menu 3 </li>
<li class="nav-item"> Menu 4 </li>
</ul>
</nav>
<!-- OLD CODE -->
<nav>
<div class="logo">
<img src="https://placehold.it/200x200" alt="logo">
</div>
<div class="menu-items">
<div class="menu-item"> Menu 0 </div>
<div class="menu-item"> Menu 1 </div>
<div class="menu-item"> Menu 2 </div>
<div class="menu-item"> Menu 3 </div>
</div>
</nav>
and the css
// MORE PROPERTIES
nav {
align-items: center;
}
nav div.logo {
position: absolute;
}
// OLD-NEW CSS
nav {
display: flex;
border: 1px solid pink;
}
nav div.logo {
border: 1px solid green;
display: flex;
align-items: center;
}
nav div.logo span {
padding: 0 0.5rem;
}
ul.nav-items {
border: 1px solid red;
display: flex;
flex-direction: row;
list-style-type: none;
margin: 0 auto;
padding: 0;
}
ul.nav-items li {
margin: 0 0.25rem;
padding: 0.5rem;
border: 1px solid blue;
}
// OLD CSS
nav {
display: flex;
}
nav div.menu-items {
display: flex;
flex-direction: row;
margin: 0 auto;
}
nav div.menu-items div.menu-item {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
Fiddle:
NEW: https://jsfiddle.net/vzgn0Lju/1/
OLD: https://jsfiddle.net/kp9nsmah/1/
I added some margins between menu options and you can tweak a little bit more but flex is way easier than using lists and lots of things. You could use spans instead of div.menu items, can remove the container for items and such. But the general idea is there.

Centering in columns with a malleable number of columns

I am attempting to list a series of same sized elements. I want these elements to display with even spacing on the right and left (vertically centered?), and evenly spaced between each other. The biggest problem is that the list needs to be able to adjust to screen size changes and number of element changes. As such the width and elements per line need to update as necessary. The bottom row should also ideally align with those above it.
This is the closest that I have been able to get so far.
HTML
<div class="outer">
<div class="inner">
</div>
</div>
... repeated as any times as there are blocks.
<div class="outer">
<div class="inner">
</div>
</div>
CSS
body {
text-align: justify;
margin:0;
width: auto;
}
.outer {
background:blue;
width: 100px;
height: 90px;
display: inline-block;
text-align: center;
}
.inner {
background:red;
width: 90px;
height: 90px;
display: inline-block;
text-align: center;
}
JSFiddle
Sounds like a job for flexbox. One of these work for you? https://codepen.io/anon/pen/VEpbjv
HTML
<ul class="flex-container space-between">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
<ul class="flex-container space-around">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
<ul class="flex-container space-evenly">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
CSS
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: flex;
}
.flex-start {
justify-content: flex-start;
}
.flex-end {
justify-content: flex-end;
}
.flex-end li {
background: gold;
}
.center {
justify-content: center;
}
.center li {
background: deepskyblue;
}
.space-between {
justify-content: space-between;
}
.space-between li {
background: lightgreen;
}
.space-around {
justify-content: space-around;
}
.space-around li {
background: hotpink;
}
.space-evenly {
justify-content: space-evenly;
}
.space-evenly li {
background: #bada55;
}
.flex-item {
background: tomato;
padding: 5px;
width: 60px;
height: 50px;
margin: 5px;
line-height: 50px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}

Aligning elements in last flexbox row

I know this question has been asked several times here, but unfortunately, none of the solutions really works and maybe there's a better way of achieving what I need in the meanwhile.
So, given the following code, you will see that the first row fits 6 elements and the second row fits 2.
.thumbnails {
display: flex;
margin: 0;
padding: 0;
list-style-type: none;
flex-flow: row wrap;
width: 640px;
height: 400px;
justify-content: space-between;
}
.thumbnail {
width: 100px;
height: 100px;
background: #ccc;
border: 1px solid #000;
}
<ul class="thumbnails">
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
</ul>
jsFiddle
What I would like to achieve is have the elements of the first row fill the space as in the code, but the elements in the second row should line up based on the first line.
Using an after pseudo-element with flex: auto like in the following code will screw up the spacing between the two elements in the last row.
.thumbnails {
display: flex;
margin: 0;
padding: 0;
list-style-type: none;
flex-flow: row wrap;
width: 640px;
height: 400px;
justify-content: space-between;
}
.thumbnails::after {
content: "";
flex: auto;
}
.thumbnail {
width: 100px;
height: 100px;
background: #ccc;
border: 1px solid #000;
}
<ul class="thumbnails">
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
</ul>
jsFiddle
So does flex-grow: 1:
.thumbnails {
display: flex;
margin: 0;
padding: 0;
list-style-type: none;
flex-flow: row wrap;
width: 640px;
height: 400px;
justify-content: space-between;
}
.thumbnails::after {
content: "";
flex-grow: 1;
}
.thumbnail {
width: 100px;
height: 100px;
background: #ccc;
border: 1px solid #000;
}
<ul class="thumbnails">
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
</ul>
jsFiddle
And so does margin-right: auto:
.thumbnails {
display: flex;
margin: 0;
padding: 0;
list-style-type: none;
flex-flow: row wrap;
width: 640px;
height: 400px;
justify-content: space-between;
}
.thumbnails::after {
content: "";
margin-right: auto;
}
.thumbnail {
width: 100px;
height: 100px;
background: #ccc;
border: 1px solid #000;
}
<ul class="thumbnails">
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
<li class="thumbnail"></li>
</ul>
jsFiddle
Is there any other way I can achieve what I need than to use dummy elements or fixed margins between the items?
I would like to remain flexible because I don't know how many items will be available and what size they have.
It appears you've covered most, if not all, methods for last-row alignment available in current flexbox.
Hopefully, a future iteration of the spec will include alignment properties such as last-row, last-column, only-child-in-a-row, etc.
In the meanwhile, we need to hack it with the methods you've listed.
There are also these options to consider: (The second option is mostly FYI, as most browsers haven't completed implementation.)
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/

Flexbox space-around except at left and right border

I have the following scenario:
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: flex;
flex-wrap:wrap;
justify-content: space-around;
}
.flex-item {
background: tomato;
padding: 5px;
width: 150px;
height: 75px;
margin-top: 10px;
line-height: 75px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
<ul class="flex-container">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
http://codepen.io/HugoGiraudel/pen/LklCv
I want one thing changed:
The left and right divs should not have a space between the parent div and itself.
When I do justify-content: space-between, that problem is solved but then the divs are no longer centered.

How can I expand li elements to container size?

I have the following HTML:
#main-menu {
background-color: blue;
border: 1px solid black;
width: 600px;
}
.menu {
list-style: none outside none;
text-align: center;
}
.menu-item {
float: left;
}
.menu-item a {
border: 1px solid red;
}
<div id="main-menu">
<ul class="menu">
<li class="menu-item">Item #1</li>
<li class="menu-item">Item #2</li>
<li class="menu-item">Item #3</li>
<li class="menu-item">Item #4</li>
</ul>
</div>
How do I make the li elements automatically expand euqally to the fixed width of the container?
Thanks in advance! :-)
CodePen link: http://codepen.io/anon/pen/JoKgXz
I've updated you codepen codes..
CSS
#main-menu {
background-color: blue;
border: 1px solid black;
width: 600px;
overflow: hidden;
}
ul, li{
margin:0;
padding:0;
}
.menu {
list-style: none outside none;
text-align: center;
}
.menu-item {
float: left;
width:25%;
}
.menu-item a {
border: 1px solid red;
}
Demo
Ensure you have a proper CSS reset and use the box-sizing:border-box property.
This option has the virtue of not requiring set widths on the li
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#main-menu {
background-color: blue;
border: 1px solid black;
width: 600px;
}
.menu {
list-style: none outside none;
text-align: center;
display: table;
width: 100%;
}
.menu-item {
display: table-cell;
}
.menu-item a {
border: 1px solid red;
color: white;
display: block;
}
<div id="main-menu">
<ul class="menu">
<li class="menu-item">Item #1
</li>
<li class="menu-item">Item #2
</li>
<li class="menu-item">Item #3
</li>
<li class="menu-item">Item #4
</li>
</ul>
</d
First remove all margin and padding from the .menu. As you have four items in the menu, add width: 25% to the .menu-item. I've added a display: block to the <a> tag to make it fill the entire width of the .menu-item. As you use float: left the menu-items won't make the .menu container grow. The .menu:after adds a clearfix to have the menu contain all menu items.
Instead of float: left you could also have opted for a display: inline-block. In this case the clearfix wouldn't be necessary, but you need to make sure that the menu items don't have any whitespace (e.g. a newline) between them. Put them on one line like ...</li><li>... otherwise there will be some space between the menu items.
If you need some padding on the menu item make sure to add box-sizing: border-box as otherwise the width will refer to the content only. This means that after adding the padding the menu item will take up more than 25% of the width, which makes the last menu item wrap to a new line.
#main-menu {
background-color: blue;
border: 1px solid black;
width: 600px;
}
.menu {
list-style: none;
text-align: center;
margin: 0;
padding: 0;
}
.menu:after {
content: '';
display: block;
clear:both;
}
.menu-item {
float: left;
width: 25%;
}
.menu-item a {
display: block;
border: 1px solid red;
}
<div id="main-menu">
<ul class="menu">
<li class="menu-item">Item #1</li>
<li class="menu-item">Item #2</li>
<li class="menu-item">Item #3</li>
<li class="menu-item">Item #4</li>
</ul>
</div>