We have an unordered list that will display up to 10 items. How can we setup the list so that it will place the first five items on the left and put the next five items into the next column (splitting equally)?
Here is the current and desired output. We tried to use CSS Flexbox, but cannot find a way to do it. Open to other ideas if flexbox cannot get it done.
Here is the current results and desired outputs.
ul {
display: flex;
flex-direction: column;
flex: 0 1 auto;
}
<div>
<ul>
<li>Assertively mesh</li>
<li>client-centered</li>
<li>niches and covalent networks</li>
<li>Uniquely e-enable</li>
<li>team driven benefits</li>
<li>rather than exceptional</li>
<li>architectures Continually</li>
<li>foster cutting-edge</li>
<li>open-source core</li>
<li>process-centric</li>
</ul>
</div>
To arrange content into predictable columns, each of five items, would seem to be a job for display: grid:
ul {
/* set the layout to grid: */
display: grid;
/* define the number of rows you
require: */
grid-template-rows: repeat(5, 1fr);
/* set the flow of the grid to follow
a columnar layout: */
grid-auto-flow: column;
}
<div>
<ul>
<li>Assertively mesh</li>
<li>client-centered</li>
<li>niches and covalent networks</li>
<li>Uniquely e-enable</li>
<li>team driven benefits</li>
<li>rather than exceptional</li>
<li>architectures Continually</li>
<li>foster cutting-edge</li>
<li>open-source core</li>
<li>process-centric</li>
</ul>
</div>
JS Fiddle demo.
Although, if you really want to use flex-box, you can:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
/* Use the flexbox layout: */
display: flex;
/* set the content direction to
columns: */
flex-direction: column;
/* let the contents wrap to
new columns once the
boundaries of the element are
reached: */
flex-wrap: wrap;
/* set the height of the containing
element, in order for the wrapping
to occur: */
height: 10em;
/* entirely irrelevant: */
list-style: none;
max-width:500px;
}
li {
/* set the height of the individual
'rows' to be 20% of the total height
of the parent, to enforce the five-
items per 'column': */
height: 2em;
line-height: 2em;
width: 45%;
}
/* Irrelevant, but allows 'column-headings'
to be styled: */
li:nth-child(5n + 1) {
font-weight: bold;
border-bottom: 1px solid #000;
}
<div>
<ul>
<li>Assertively mesh</li>
<li>client-centered</li>
<li>niches and covalent networks</li>
<li>Uniquely e-enable</li>
<li>team driven benefits</li>
<li>rather than exceptional</li>
<li>architectures Continually</li>
<li>foster cutting-edge</li>
<li>open-source core</li>
<li>process-centric</li>
</ul>
</div>
JS Fiddle demo.
I would use CSS columns for this:
ul {columns: 2;}
li {list-style-position: inside;}
<ul>
<li>Assertively mesh</li>
<li>client-centered</li>
<li>niches and covalent networks</li>
<li>Uniquely e-enable</li>
<li>team driven benefits</li>
<li>rather than exceptional</li>
<li>architectures Continually</li>
<li>foster cutting-edge</li>
<li>open-source core</li>
<li>process-centric</li>
</ul>
Note that 'display: grid' has pretty bad browser support, while columns (and flexbox) score better.
Related
Is it possible to make flex children align vertically?
Example
In this case, the left "softwaredevelopment" box should increase a little so that the above "react" align with the "react" underneath. The same goes with "web", "software" and so on..? Obviously, the slight misalignment of the boxes in the picture beneath is slightly annoying...
Does a property for flexbox exist that does what I described?
The solution should be dynamic
Flexbox is great for horizontal layout control, but was not designed to handle vertical layout. Consider CSS Grid with a touch of JavaScript for layouts like this. Once we decide on a number of columns (7, in this case), we can add a bit of JavaScript that decides on the span of columns based on text length. This is a simple prototype, but could be further developed to deal with edge-case rules.
let listItems = document.querySelectorAll(".grid li");
listItems.forEach(item => {
const len = item.innerText.length;
if (len > 15 && len < 20) {
item.classList.add('span-2');
} else if (len >= 20) {
item.classList.add('span-3');
} // etc.
});
.grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-auto-rows: 1fr;
margin: 0;
padding: 0;
list-style: none;
}
.grid li {
text-align: center;
border: .5px solid;
display: flex;
align-items: center;
justify-content: center;
font-size: 100%;
padding: .35em;
}
.span-2 {
grid-column: span 2;
}
.full-width {
grid-column: 1 / -1;
}
<ul class="grid">
<li class="full-width">Show all</li>
<li>Python</li>
<li>NodeJS</li>
<li>React</li>
<li>Web</li>
<li>Software</li>
<li>React</li>
<li>Webdev</li>
<li>Sofware Development</li>
<li>React</li>
<li>Crazy Developers</li>
<li>Web</li>
<li>React</li>
<li class="full-width">Sofware Development</li>
</ul>
jsFiddle
I am creating a navigation bar in Reactjs with four elements. These items are a simple unordered list with some css using flexbox to align them horizontaly.
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<ul/>
What I want to achieve is: When a list item is selected, align the selected list item to center. I have added a professional picture for clarification. This change will later be animated for a smooth transition, like a carousel.
Following is the css for <ul> tag.
ul {
list-style-type: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
What I've tried is to use the align-self: center on the one of the <li> items, but with no luck.
Does anyone have any experience with doing something similar? I am open for all types of solutions, even those that does not use flexbox.
Thank You!
Do the list elements have a fixed with, and do you know how many items there are? If so, you can calculate the center of the list, the item offset, and add a CSS transform.
Example:
You have a list of four items.
Each item has width equal to 100px.
The total width of the list is therefore 400px.
The center point of the list is 200px from the left.
The center point of item number two is 150px from the left. We therefore have to move the list 200px - 150px = 50px from the left.
The center point of item number four is 350px from the left. We therefore have to move the list 200px - 350px = -150px from the left.
If your list is dynamic, both regarding to list length and item width, you can use Element.getBoundingClientRect() to find the elements' dimensions, and use the same calculations as above.
Codepen: https://codepen.io/anon/pen/vjJMVL
HTML:
<ul class="selected-2">
<li>1</li>
<li class="selected">2</li>
<li>3</li>
<li>4</li>
</ul>
<ul class="selected-4">
<li>1</li>
<li>2</li>
<li>3</li>
<li class="selected">4</li>
</ul>
CSS:
ul {
display: flex;
justify-content: center;
list-style: none;
}
li {
width: 80px;
height: 80px;
background-color: #eee;
margin: 10px;
}
.selected {
background-color: #ccc;
}
.selected-2 {
transform: translateX(50px)
}
.selected-4 {
transform: translateX(-150px)
}
Calculate the clicked <MenuItem> center by using Element.getBoundingClientRect() to get it's left, and width, and pass it to the parent (<Menu>). In the parent use the <ul>s ref to get it's left and width with Element.getBoundingClientRect(). Calculate the moveTo state, and update the <ul>s style transform: translateX() accordingly:
const { Component } = React;
const items = ['One', 'Two', 'Three', 'Four'];
class MenuItem extends Component {
clickHandler = (e) => {
const { left, width } = e.target.getBoundingClientRect();
const itemCenter = left + width / 2;
this.props.updateCenter(itemCenter);
}
render() {
const { children } = this.props;
return (
<li onClick={this.clickHandler}>{children}</li>
);
}
}
class Menu extends Component {
state = {
moveTo: 0
};
updateCenter = (itemCenter) => {
const { left, width } = this.ul.getBoundingClientRect();
//this.ul.style.transform = `translateX(${center}px)`;
this.setState(() => ({
moveTo: left + width / 2 - itemCenter
}));
};
render() {
const { items } = this.props;
const { moveTo } = this.state;
return (
<nav>
<ul ref={(ul) => this.ul = ul} style={{
transform: `translateX(${moveTo}px)`
}}>
{
items.map((text) => (
<MenuItem key={text}
updateCenter={this.updateCenter}>
{text}
</MenuItem>
))
}
</ul>
</nav>
);
}
}
ReactDOM.render(
<Menu items={items} />,
demo
);
/** demo only - display the center **/
body::before {
position: absolute;
left: 50%;
height: 100vh;
border-right: 1px solid black;
content: '';
}
nav {
overflow: hidden;
}
ul {
list-style-type: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
li {
padding: 1em;
border: 1px solid black;
cursor: pointer;
}
ul li:not(:last-child) {
margin: 0 1em 0 0;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="demo"></div>
Since i don't fully get what you want, this is the best i could have came up with, applying absolute positioning to the selected one and have it overlap the others with z-index
document.querySelectorAll('li').forEach(function(li){
li.addEventListener('click',function(e){
document.querySelectorAll('li').forEach(function(obj){
obj.classList.remove('selected');
});
e.target.classList.add("selected");
});
});
ul {
list-style-type: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
li{
border:1px solid;
padding:10px;
cursor:pointer;
position:relative;
transition:all ease 1s;
margin:0 20px;
}
.selected{
transform:scale(2.1);
background:white;
box-shadow:0px 0px 55px black;
position:absolute;
z-index:5;
}
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
I'm trying to create the following header using CSS:
This is my attempt so far using CSS grid:
HTML:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="jumbotron">
<div class="grid">
<div class="a">
28
</div>
<div class="b">
clubs
</div>
<div class="c">
/
</div>
<div class="d">
48
</div>
<div class="e">
virtual
</div>
<div class="f">
gyms
</div>
</div>
CSS:
.jumbotron {
background: linear-gradient(141deg, rgb(0,223,179), rgb(34,198,252));
}
.grid {
display:grid;
grid-template-columns: 50px 50px 50px 50px;
color:white;
}
.a{
grid-column: 1;
grid-row: 1/span 2;
font-size:35px;
}
.b{
grid-column: 2;
grid-row: 2;
}
.c{
grid-column: 3;
grid-row: 1/span 2;
font-size:35px;
}
.d {
grid-column: 4;
grid-row:1/span 2;
font-size:35px;
}
.e {
grid-column:5;
grid-row:1;
}
.f {
grid-column:5;
grid-row:2;
}
https://codepen.io/anon/pen/jGKwEL
I don't know if I'm overthinking it but this is the best solution I can come up with to make the stacked text somewhat align. It's very tedicous however to make look exactly like the picture and it includes a lot of CSS classes. Any other way to approach this or am I on the right track?
Edit: this what I ended up doing with help of the answers to this question: https://codepen.io/anon/pen/jGKwEL
You don't have to use CSS grid: just because it is available does not mean that you have to use it, or that it is relevant for your usecase. In your layout requirement, it is more suitable to use a mix of display: flex and some simple relative positioning to get the baseline of the text to line up.
First, with the markup, you can simply use a <ul>:
<ul>
<li>
<span class="count">28</span>
<span class="text">clubs</span>
</li>
<li>
<span class="count">48</span>
<span class="text">virtual<br />gyms</span>
</li>
</ul>
With regards to styling:
use display: flex on the <ul> parent so that the child elements will be arranged horizontally
the slanted border can simply be emulated using border-right, and we disable it on the last child using the li:last-child selector
the baseline alignment of the text/description next to the number requires manual adjustment, just play around with some values with bottom offset
use transform: skew(...) to slant your text uniformly, instead of relying on italics. This will lead to uniform slanting of the text and the separators :)
The outcome will look something like this:
Here is a quick proof-of-concept I have whipped up, based on the suggested changes listed above:
.jumbotron {
background: linear-gradient(141deg, rgb(0, 223, 179), rgb(34, 198, 252));
}
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
justify-content: flex-end; /* Align to right */
}
ul li {
transform: skew(-10deg);
border-right: 3px solid #fff;
padding: 0 20px;
display: flex;
align-items: flex-end; /* Align to bottom */
}
ul li:last-child {
border: none;
}
ul li span {
color: white;
line-height: 1em;
font-weight: bold;
}
ul li span.count {
font-size: 45px;
margin-right: 10px;
}
ul li span.text {
text-transform: uppercase;
position: relative;
bottom: .35em; /* Adjust this value manually */
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="jumbotron">
<ul>
<li>
<span class="count">28</span>
<span class="text">clubs</span>
</li>
<li>
<span class="count">48</span>
<span class="text">virtual<br />gyms</span>
</li>
<li>
<span class="count">33</span>
<span class="text">active<br />players</span>
</li>
<li>
<span class="count">15</span>
<span class="text">inactive<br />players</span>
</li>
</ul>
</div>
Here's an example using a list, :after for styling the slashes, and spans for the different parts of one item. You can just duplicate the <li>'s to add more items, without the need for futher classes. I hope it's the way you need it :)
You could use flexbox as an alternative, but I personally think there is no need for it in this case.
https://codepen.io/anon/pen/YrvQMp
I have a problem where I have created a header component but there is still whitespace above the header on every page I pull the header component in
this is my entire header component:
import React from 'react';
import { Link } from 'react-router';
import './index.scss';
export default class Header extends React.Component {
render() {
return(
<div className="container">
<ul>
<div className="links">
<li><Link to="quizzes">Quizzes</Link></li>
</div>
<div className="links">
<li><Link to="categories">Categories</Link></li>
</div>
<div className="links">
<li><Link to="create">Create</Link></li>
</div>
</ul>
</div>
)
}
}
and this is my entire css
body {
margin: 0;
}
.container {
margin: 0;
background-color: #bec0c4;
height: 50px;
width: 100%;
}
.container ul{
display: flex;
flex-direction: row;
font-size: 20px;
justify-content: space-between;
list-style-type: none;
width: 90%;
}
I have seen many answers saying to set the margin to 0 but this is still giving me whitespace at the top. if i set margin-top to -20px, it removes it but i dont like this solution
Most browsers (eg. Chrome) come with a default set of rules (user agent stylesheet) and set rules like margin in ul's, so you likely have a margin-top (-webkit-margin-before: 1em;) set to your ul.
Set margin-top: 0 on the ul will remove the space:
ul {
margin-top: 0;
}
I've set the margin for ul to zero (and included padding to force a default reset). Let me know if this meets your requirements.
You may want to have a look at tools like normalize.css for future use.
body {background-color: red;}
body, ul {
margin: 0;
padding: 0;
}
.container {
background-color: #bec0c4;
height: 50px;
width: 100%;
}
.container ul {
display: flex;
flex-direction: row;
font-size: 20px;
justify-content: space-between;
align-items: center;
list-style-type: none;
width: 90%;
height: 100%;
}
<div class="container">
<ul>
<div class="links">
<li>
<a>Quizzes</a>
</li>
</div>
<div class="links">
<li>
<a>Categories</a>
</li>
</div>
<div class="links">
<li>
<a>Create</a>
</li>
</div>
</ul>
</div>
I added a margin: 0 to .container ul to and it doesn't leave any whitespace. It was leaving whitespace before over the Header component. Here's a picture of how it looks now.
First check the page using inspect element (Ctrl+shift+I = for google chrome in windows).
Then check if <ul> is consuming the whitespace, then set ul { margin:0; } or for anyother element which is consuming the space. Hope it helps !
In my case, following code snippet worked (Mentioned this in app_directory/src/index.css)
* {
margin-top: 0;
}
You have two ways to get rid of this issue!
One as mentioned by most of the people do 'margin: 0;' or 'margin-top: 0;' to your ul tag or the child you have in your header.
or
Second as mentioned by Bahu, you can go to your index.css or App.css the parent components css files and do this.
* {
margin: 0; /* or margin-top: 0; */
}
If you apply a reset.css on your code, ensure your page loads this reset.css. If you are loading it from the homepage for example -index.js-, and then you open your browser directly on, let's said about_us' page -about_us.js-, then if about.us.js fails to load the reset.css you will have a standard page with all the browser's default styles.
So, always ensure you are loading your reset.css on all your routes to avoid default browsers' page overflowing.
hope you can help me.
I am trying to create a navigation with a variable amount of list elements. Now I want to automatically set the height of the list elements based on the height of the surrounding div element, and the number of list elements that are in the div. Is there a way to do so, or can I only do it the other way around, by simply not giving the div a height value, but rather give the list elements a fixed height?
Hope you can help me.
#nav ul{
margin: 0;
padding: 0;
list-style: none;
}
#nav{
margin-top: 30px;
width: 19%;
background-color: red;
float:left;
border-top: 1px solid black;
}
#nav ul li{
text-align: center;
width: 100%;
background-color: yellow;
height: 50px;
margin-top: 20px;
line-height: 50px;
border-bottom: 1px solid black;
border-left: 1px solid black;
transform: rotate(20deg);
}
You can use the below code,it will definitely work
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div id="change" style="height:200px;border:1px solid black">
<ul>
<li>HI</li>
<li>Hello</li>
<li>Bye</li>
<li>Byesdfsd</li>
<li>sdfsd</li>
<li>sdfsd</li>
</ul>
</div>
<script>
var height=document.getElementById("change").style.height;
height=height.replace("px","");
var lis=document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
lis[i].style.height=(parseInt(height))/(parseInt(lis.length))+"px";
console.log("getting height "+lis[i].style.height);
}
</script>
</body>
</html>
So you can give the height of the div in a class or in the inline style,but you will have to change the code accordingly in the js part for fetching the height of the div.
I have got the li tags and then depending on their number i have divided the height of the enclosing div by the number of list tags
So basically what you want is that if the div is 100px high and you have 4 items in the list, each item should be 25px high, and if you have 5 items then each should be 20px high. Is it correct?
In this case, if you don't want to resort to javascript, you can use flexbox.
Here, javascript is only used to dinamically add items to the menu in order to demonstrate flexbox behavior:
var menuEl = document.getElementById('menu');
document.getElementById('addMenuItemBtn').onclick = function () {
var numberOfItems = menuEl.childElementCount;
// create a new menu item
var newListElement = document.createElement('li');
newListElement.appendChild(document.createTextNode('Menu item ' + (numberOfItems + 1)));
newListElement.setAttribute('class', 'item');
// append the new item
menuEl.appendChild(newListElement);
}
document.getElementById('removeMenuItemBtn').onclick = function () {
var numberOfItems = menuEl.childElementCount;
if (numberOfItems > 1) {
// if there are at least 2 items, remove the last item
var lastItemIndex = numberOfItems - 1;
var lastItem = menuEl.children[lastItemIndex];
lastItem.remove();
}
}
.container {
list-style: none;
margin: 0;
padding: 0;
width: 320px;
height: 240px; /* enough for 6 items with a height of 40px */
background-color: #DDD;
display: flex;
flex-direction: column;
}
.item {
width: 100%;
margin: 5px;
padding: 5px;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 30px;
}
<ul class="container" id="menu">
<li class="item">Menu item 1</li>
<li class="item">Menu item 2</li>
</ul>
<input type="button" value="Add menu item" id="addMenuItemBtn">
<input type="button" value="Remove menu item" id="removeMenuItemBtn">
Since the container is 240px high and items have a minimum height of 40px (flex-basis: 30px + margin: 5px), there is enough space for 6 items. If you add more than 6 items, the extra elements will overflow.
You can read more about flexbox in this article on css-tricks.com.
You'll likely want to change a lot of things in my snippet, it's just a proof of concept!
Just keep in mind that some old browsers don't support it, or support it with
a legacy syntax.