css: sort divs/lis into two columns - css

Suppose there are two kinds of elements, let's say words and numbers. They should be sorted into two columns. For the example I'm using listitems, but I don't mind changing to divs or something else if that helps.
<div id="container">
<ul>
<li>foo</li>
<li>bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li>baz</li>
</ul>
</div>
Right now I'm achieving this somewhat by using margins, with the following css:
#container {
width: 500px;
margin: auto;
}
li {
float: left;
width: 200px;
background-color: #eee;
margin-bottom: 2px;
margin-right: 300px;
}
.num {
float: right;
margin-right: 0px;
margin-left: 300px;
}
resulting in
http://jsfiddle.net/he13vug4/
What would be a more elegant way to achieve this?
How could I make the numbers "start" (in terms of vertical position) already besides "bar" or even "foo"? (The next word should, however, only start below the numbers). That is, I'd like
or
instead of

They should be sorted into two columns, side by side
Do you need support for older browsers? If not, CSS Grid could help you
Result
#container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: dense;
gap: 10px;
width: 500px;
margin: auto;
list-style: none;
}
li {
background-color: #eee;
}
.word {
grid-column: 1;
}
.num {
grid-column: 2;
}
<ul id="container">
<li class="word">foo</li>
<li class="word">bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li class="word">baz</li>
</ul>
And same code on JSFiddle

Use only left floating and play with clear and margin like below:
#container {
width: 500px;
margin: auto;
}
ul {
list-style:none;
}
li {
float: left;
width: 200px;
background-color: #eee;
margin-bottom: 2px;
}
li + li:not(.num) {
clear:both;
}
li + li.num {
margin-left:10px;
}
li.num + li.num {
margin-left:210px;
}
<div id="container">
<ul>
<li>foo</li>
<li>bar</li>
<li class="num">1</li>
<li class="num">2</li>
<li>baz</li>
<li>baz</li>
<li class="num">1</li>
<li class="num">2</li>
<li class="num">3</li>
<li>baz</li>
<li>baz</li>
</ul>
</div>

Related

How to use "clearfix" css in nested blocks?

I'd found, that css "clearfix" example not work properly when there are nested float:left blocks.
Here is an example:
.left {
float: left;
width: 100px;
height: 200px;
background: green;
}
.right {
margin-left: 100px;
background: yellow;
}
.clearfix:after {
content: ' ';
display: table;
clear: both;
}
ul.clearfix {
padding: 10px;
}
.clearfix li {
float: left;
list-style: none;
border: 1px solid red;
}
<div class="left">
Image
</div>
<div class="right">
<ul class="clearfix">
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
<p>Some description</p>
</div>
It shows, that text "some text" appears quite under "left" block.
While there presents huge space after list of elements with "clearfix" css.
Any ideas to fix it?
In this particular case you can make the p inline-block and you will not need clearfix (at least inside the right element). You may need to clear after the right element if you will have more content.
.left {
float: left;
width: 100px;
height: 200px;
background: green;
}
.right {
margin-left: 100px;
background: yellow;
}
ul.clearfix {
padding: 10px;
}
.clearfix li {
float: left;
list-style: none;
border: 1px solid red;
}
p {
display:inline-block;
width:100%;
}
<div class="left">
Image
</div>
<div class="right">
<ul class="clearfix">
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
<p>Some description</p>
</div>
You can use CSS clear: both; for your paragraph
.left {
float: left;
width: 100px;
height: 200px;
background: green;
}
.right {
margin-left: 100px;
background: yellow;
}
.list:after {
content: ' ';
display: table;
clear: both;
}
.footer{ clear: both;}
.list li {
float: left;
padding: 10px;
list-style: none;
border: 1px solid red;
}
<div class="left">
Image
</div>
<div class="right">
<ul class="list">
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
</div>
<div class="footer"><p>Some description</p></div>
So, my estimations about float:left in different containers are mistake. Float property puts all blocks in one flow, regardless their containers. So, meaning "nested" blocks towards this float blocks is useless.
The other problem is - that container has no size without clearfix. The solution is - to set ul.overflow:hidden

How do I get navigation buttons in the same line but position them differently?

What I'm trying to achieve:
I tried using a nested unordered list but found it difficult to set 2 buttons to the left and 2 buttons to the right, I am now trying something a little different but still no success, also I want the distance between these button to stay constant when viewed on different sized displays. Any help would be greatly appreciated.
(If anyone is familiar with xml you'll know that that its possible to give things a weight. so say you have 3 items in a box and you give them all a weight of 1 each items would take up a third of the space in the box, is there anything like this in html?)
This is what I have so far.
#navContainer nav {
display: inline-block;
}
#nav1 {
background: aqua;
position: absolute;
left: 0;
}
#nav2 {
background: pink;
position: absolute;
right: 0;
}
<div id="navContainer">
<nav id="nav1">
<ul>
<li>Highscores</li>
<li>Help</li>
</ul>
</nav>
<nav id="nav2">
<ul>
<li>Signin</li>
<li>Signup</li>
</ul>
</nav>
</div>
How about a flexbox approach, then you only need one list
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
width: 100%;
justify-content: space-between; /* spreads things across the horizontal line */
}
.signin {
margin-left: auto; /* moves this to the right */
margin-right: 10px; /* gap between signin and signup */
}
.help {
margin-right: auto; /* don't need this really */
margin-left: 10px; /* gap between highscores and help */
}
<nav id="nav1">
<ul>
<li class="highscores">Highscores</li>
<li class="help">Help</li>
<li class="signin">Signin</li>
<li class="signup">Signup</li>
</ul>
</nav>
you can use flexbox,
just using 1 ul removing extra markup unnecessary
ul {
display: flex;
justify-content: space-between;
align-items: flex-end;
background: lightblue;
height: 160px;
margin: 0;
padding: 0;
}
li {
background: purple;
border-radius: 10px;
padding: 10px;
margin: 0 10px;
list-style: none;
color: white
}
li:nth-last-of-type(2) {
margin-left: auto
}
<ul>
<li>Highscores</li>
<li>Help</li>
<li>Signin</li>
<li>Signup</li>
</ul>
just using 1 nav and 2 ul if you want to keep the container at a minimal state
nav{
display: flex;
justify-content: space-between;
align-items: flex-end;
height: 160px;
background: lightblue
}
ul:last-of-type {
margin-left: auto
}
ul {
display: flex;
margin: 0;
padding: 0;
}
li {
background: purple;
border-radius: 10px;
padding: 10px;
margin: 0 10px;
list-style: none;
color: white
}
<nav id="navContainer">
<ul>
<li>Highscores</li>
<li>Help</li>
</ul>
<ul>
<li>Signin</li>
<li>Signup</li>
</ul>
</nav>
You can do it with the Flexbox:
* {margin:0;padding:0;box-sizing:border-box}
html, body {width:100%}
ul {
list-style: none;
display: flex;
}
ul > li {
margin: 5px;
padding: 5px 0;
width: 125px;
color: #fff;
text-align: center;
text-shadow: 1px 1px 1px #000;
font-weight: bold;
text-transform: uppercase;
border-radius: 25px;
background: purple;
}
#navContainer {
display: flex;
justify-content: space-between;
}
<div id="navContainer">
<nav id="nav1">
<ul>
<li>Highscores</li>
<li>Help</li>
</ul>
</nav>
<nav id="nav2">
<ul>
<li>Signin</li>
<li>Signup</li>
</ul>
</nav>
</div>
I don't understand ur question completely, but I think this might be your solution:
<html>
<head>
<title>Project</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="CSS/pageFormatting.css">
<style>
#navContainer nav {
display: inline-block;
}
li {display:inline;margin:20px;}
#nav1 {
background-color: aqua;
position: absolute;
left: 0;
display:inline-block;
}
#nav2 {
background-color: pink;
position: absolute;
right: 0;
display:inline-block;
}
</style>
</head>
<body>
<div id="navContainer">
<nav id="nav1">
<ul>
<li>Highscores</li>
<li>Help</li>
</ul>
</nav>
<nav id="nav2">
<ul>
<li>Signin</li>
<li>Signup</li>
</ul>
</nav>
</div>
</body>
</html>
I added tags and the head and body tags. Within those style tags I wrote the css. nav1 is now left en nav2 is now right.
Tell me if I'm wrong.

Mouseenter event on parent when a child is absolute positioned

I'm tring to make a simple drop-down menu, which would be triggered on hover event over some element and stay active as long as the cursor is over that element or is over the dropdown list.
Sample code:
HTML
<div class="header">
<div class="items">
<div class="item">
<span>Caption</span>
</div>
<ul class="items_hidden">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
<input type="text">
CSS
.items {
float: right;
position: relative;
}
.item {
text-align: right;
}
.items_hidden {
display: none;
margin-top: 7px;
list-style: none;
z-index: 2000;
width: 80px;
border: 1px solid #f2f2f2;
text-align: left;
padding: 10px;
color: #333;
line-height: 30px;
border-bottom: 3px solid #f2f2f2;
}
input {
width: 100%;
}
JS
$(function() {
$('.items').on('mouseenter', function(e) {
$('.items_hidden').show();
});
$('.items').on('mouseleave', function(e) {
$('.items_hidden').hide();
});
});
I got that working, when the dropdown list is positioned relative, but the problem is once the list is displayed, it causes all following content to move down.
Here is an example: https://jsfiddle.net/2ya06aLo/
Another way would be to position the list absolute, so it wouldn't affect the content below. But in that case the list disappears as soons as I move the cursor out of 'Caption' (in contrast with the first fiddle).
Here is the second example https://jsfiddle.net/8L6ojqLm/
What would be a solution to make the list behave like in 1 and at the same time do not affect the rest of the content like in 2 ?
You can don't use JS
Example
.items {
float: right;
position: relative;
}
.item {
text-align: right;
padding: 10px;
}
.items_hidden {
position: absolute;
right: 0;
top: 20px;
display: none;
margin-top: 7px;
list-style: none;
z-index: 2000;
width: 80px;
border: 1px solid #f2f2f2;
text-align: left;
padding: 10px;
color: #333;
line-height: 30px;
border-bottom: 3px solid #f2f2f2;
}
input {
width: 100%;
}
.items:hover .items_hidden{
display: block;
}
<div class="header">
<div class="items">
<div class="item">
<span>Caption</span>
</div>
<ul class="items_hidden">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
<input type="text">
Live JSFiddle - https://jsfiddle.net/grinmax_/8L6ojqLm/1/
Couldn't it be done via pure css?
https://www.w3schools.com/howto/howto_css_dropdown.asp
Maybe this would help.
.navigation {
width: 100%;
}
.mainmenu, .submenu {
list-style: none;
padding: 0;
margin: 0;
}
.mainmenu a {
}
.mainmenu a:hover {
background-color: #D90000;
}
.mainmenu li:hover .submenu {
display: block;
max-height: 400px;
}
.submenu{
max-height: 400px;
}
.submenu a {
background-color: #FF4D4D;
}
.submenu a:hover {
background-color: #D90000;
}
.submenu{
overflow:hidden;
display:none;
}
<nav class="navigation"><!-- pocetak navigacije -->
<ul class="mainmenu">
<li>Link</li>
<li class="start">Link
<ul class="submenu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
<li>Home</li>
</ul>
</nav>
To take up the comment of CBroe: The problem seems to be the "gap" between the and the element. To remove it you could either
give the "item"-Element a height so that it "reaches down" to the ul-element or
or remove the margin-top of the ul-element

Hover element to effect sibling element

I have a navigation bar with a list of links and a search bar. It looks like this:
<ul>
<li class="link">Link 1</li>
<li class="link">Link 2</li>
<li class="link">Link 3</li>
<li class="link search">search</li>
</ul>
When the user hovers the "search" element, I want to
Apply a width of 500px to the hovered search elements
Apply a margin of -150px to the sibling "link" element
The CSS that I've written to do this is:
ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
float: right;
}
.link {
width: 150px;
float: left;
line-height: 80px;
}
.search {
background: red;
width: 50px;
}
.search:hover{
width: 500px
}
.search:hover + .link {
margin-left: -150px;
}
This however has no effect on the sibling "link" elements
With pure CSS, is it possible to apply the the declarations "margin-left: -150px" on the hover of "search"?
I've created a fiddle here to illustrate the problem
https://jsfiddle.net/qut1nz9j/
If you use flex you can do like this. (Current browser support ~96%)`
The trick is you put the search link first in your markup and use order to show it last. With this you can use the sibling selector ~ to achieve what you want.
nav {
width: 700px;
background: green;
height: 80px;
float: left;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
display: inline-flex;
}
.link {
width: 150px;
line-height: 80px;
order: 1;
}
.search {
background: red;
width: 50px;
order: 2;
}
.search:hover {
width: 500px
}
<nav>
<span>Site Name</span>
<ul>
<li class="link search">search</li>
<li class="link">Link 1</li>
<li class="link">Link 2</li>
<li class="link">Link 3</li>
</ul>
</nav>
Thanks to Joum, here is a nice addition to my solution: https://jsbin.com/yipujadewi/edit?css,output
If someone really need to target previous sibling and can't use flex, here is an abuse of direction: ltr/rtl in combination with display: table.
Src: CSS Tables, Invert order of displayed content
nav {
width: 700px;
background: green;
height: 80px;
float: left;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
width: 500px;
display: inline-table;
direction: rtl;
}
.link {
width: 150px;
line-height: 80px;
display: table-cell;
direction: ltr;
text-align: left;
}
.search {
background: red;
width: 50px;
}
.search:hover {
width: 500px
}
.search:hover ~ .link {
color: #fff;
}
<nav>
<span>Site Name</span>
<ul>
<li class="link search">search</li>
<li class="link">Link 3</li>
<li class="link">Link 2</li>
<li class="link">Link 1</li>
</ul>
</nav>

CSS keep menu in container and expand background to full screen

The picture below shows what I would like to get.
It is a menu within a container, where the menu may wrap to multiple lines when the window/screen gets too narrow for all menu items to fit in. At the same time I would like the menu to have a background which expands to full screen in width, while expanding in height with the menu when it gets wrapped to multiple lines. Currently I think this is not possible with CSS, but I am also just a CSS amateur. My current solution involves #media queries to set the height of the menu background for resolutions where wrapping appears. This does not take into account that font-size could change, thus making each line of menu higher.
Here is a jsFiddle with a basic setup, which does NOT what I want:
https://jsfiddle.net/n3jmyq2f/3/ (Edited, was not the final version)
Here is the code:
<div class="container">
<div class="menu_wrap">
<div class="menu_bg"></div>
<div class="menu">
<ul>
<li>item 1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
</ul>
</div>
</div>
<div class="content">It's me, Mario!</div>
CSS:
.container {
width:50%;
margin: 0 auto;
background:lightgreen;
height:300px;
}
.menu_bg{
position: absolute;
background: #afafaf;
width: 100%;
left:0;
height:30px;
z-index: -1;
}
ul {
height:30px;
background: #afafaf;
}
li {
display:inline-block;
}
The first option is the simplest.
Stop thinking of the .container as something that must contain everything. It's just a class that can be reused as and when required.
If you take the menu div out of the "container" but put a .container div inside you get the effect you are looking for.
JSfiddle Demo
*,
body {
padding: 0;
margin: 0;
}
.container {
width: 50%;
margin: 0 auto;
background: lightgreen;
}
.menu {
background: #afafaf;
}
ul {
border: 1px solid green;
}
li {
display: inline-block;
}
.content {
height: 300px;
}
<div class="menu">
<div class="container">
<ul>
<li>item 1
</li>
<li>item2
</li>
<li>item3
</li>
<li>item4
</li>
<li>item5
</li>
<li>item6
</li>
</ul>
</div>
</div>
<div class="container">
<div class="content">It's me, Mario!</div>
</div>
2nd Option
Use a pseudo-element
*,
body {
margin: 0;
padding: 0;
}
.container {
width: 50%;
margin: 0 auto;
background: lightgreen;
height: 300px;
}
ul {
background: #afafaf;
position: relative;
border: 1px solid green;
}
ul:before {
content: '';
position: absolute;
height: 100%;
background: inherit;
width: 100vw;
left: 50%;
transform: translateX(-50%);
z-index: -1
}
li {
display: inline-block;
}
<div class="container">
<div class="menu">
<ul>
<li>item 1
</li>
<li>item2
</li>
<li>item3
</li>
<li>item4
</li>
<li>item5
</li>
<li>item6
</li>
</ul>
</div>
<div class="content">It's me, Mario!</div>
</div>
JSfiddle Demo
if in .container you change
width:50%;
to
width:100%;
it will do it
fiddle
you could also use the .menu-wrap class (which I've seen in your markup) to do this

Resources