I have a page layout with the following html structure:
<div class="row">
<div class="col3">test 1</div>
<div class="col3">test 2</div>
<div class="col3">test 3</div>
</div>
Using the following css, I wanted to make a simple, responsive layout:
.row {
width: 100%;
display: block;
padding-left: 1.25%;
padding-right: 1.25%;
margin: 0 auto 15px auto;
}
.col3 {
width: 30%;
display: inline-block;
margin: 0 1.25%;
border: none;
}
Why is it when I shrink my page to 30% of the width of my screen, the last column drops down underneath the other rows?
Is there something im not accounting for? I would have thought it would have just continued to get narrower and narrower. What causes it to create a content break, and drop down a row.
Screenshots:
It's from display: inline-block. If you float your columns to the left they will work as expected.
When you use display: inline-block spaces/returns etc between the elements that have inline-block applied to them will be taken into account and rendered. You can think of it as adding a single space between each inline-block element.
This is the main downside of using display: inline-block over floats in my humble opinion.
.col3 {
float: left;
width: 30%;
margin: 0 1.25%;
border: none;
}
You could also remedy this by doing the following if you wanted to continue using display: inline-block but they're hackerish. I would advise against either of these solutions.
no space between elements
<div class="col3">test 1</div><div class="col3">test 1</div><div class="col3">test 1</div>
comments between elements
<div class="col3">test 1</div><!--
--><div class="col3">test 1</div><!--
--><div class="col3">test 1</div>
Your problem lies with the lines
.col3 {
..
width:30%;
margin: 0 1.25%;
..
}
As width is 30% of the row, but while you are narrowing it down, the margin is actually getting wider with respect to the row, its a common thing which happens to inline-block display type.
If you drop the margin line, or simply change the width of the margin to
margin: 0 1%;
it would be fixed.
No need to worry about fixing inline-blocks, or having to deal with its downsides.
Related
I want to make a very simple navbar with HTML and CSS (so simple I prefer to do it without Bootstrap), made of just three short texts, situated on the leftmost, center, and rightmost part of one single line.
My idea is that I cut the line in two halves, put the left & middle part in the first half, and the rightmost part in the second half. So I tried the following :
.div_left {
float: left;
position: absolute;
}
.div_right {
float: right;
text-align: right;
position: absolute;
}
.container_for_mininavbar {
width: 100%;
position: absolute;
}
.mininavbar_left_half {
width: 50%;
float: left;
position: absolute;
}
.mininavbar_right_half {
width: 50%;
float: right;
position: absolute;
}
<div class="container_for_mininavbar">
<div class="mininavbar_left_half">
<div class="div_left">Left Text</div>
<div class="div_right">Center Text</div>
</div>
<div class="mininavbar_right_half">
<div class="div_right">Right Text</div>
</div>
</div>
But that doesn't work, all the texts are on top of each other.
What is the correct way to do this?
Just remove position absolute.
I'll suggest to use flexbox to do this and don't use float anymore
.div_left {
float: left;
}
.div_right {
float: right;
text-align: right;
}
.container_for_mininavbar {
width: 100%;
}
.mininavbar_left_half {
width: 50%;
float: left;
}
.mininavbar_right_half {
width: 50%;
float: right;
}
<div class="container_for_mininavbar">
<div class="mininavbar_left_half">
<div class="div_left">Left Text</div>
<div class="div_right">Center Text</div>
</div>
<div class="mininavbar_right_half">
<div class="div_right">Right Text</div>
</div>
</div>
And this is a little example with flexbox
.container_for_mininavbar {
width: 100%;
border: 1px;
display: flex;
}
.container_for_mininavbar div {
flex: 0 1 33.33%;
border: 1px solid #000;
text-align: center;
}
<div class="container_for_mininavbar">
<div>Left Text</div>
<div>Center Text</div>
<div>Right Text</div>
</div>
So, you want some links to the left, some to the center and the rest to the right?
The easiest and most effective way (by me) is to use Flexbox.
So, you need a container div, named "navigation" (or however you want) which contains another 2 divs, one for the left side, and one for the right side.
Now, assign to the navigation div, the following:
display: flex; /* is going to display the div flex */
justify-content: space-between; /* this is where magic happens, it will push the items from the nav div, which are the other 2 divs to the left and right side*/
flex-flow: row nowrap;
The first property is for it to be displayed in a row, you can set it to column too, and the nowrap is not going to let the content to deform in some sort of way, if you set that to wrap, of course, it will wrap under, but I suggest letting that nowrap, but I don't think flex-flow is 100% neccesary in this situation
Now, the flexbox works for the other 2 divs as well, maybe you want the links in the left-side div to be "justify-content: space-between;" or space-evenly, or center, space-around, etc.
I recommend you to learn Flexbox, it's very useful and simple to use.
I hope this answer will help you. :)
And to center the links in each div, use align-items: center; , it will center the links on the Y scale. (which is top-bottom)
EDIT: If you want center links too, it's the same thing, just make another div between the left-side div and the right div. And the justify-content: space-betweeen; it's going to have the same effect. And if you don't link how it scales, you can always use the margins in the div.
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 3 years ago.
The inner divs will be thumbs that are being continuously added and eventually wrap to next row.
The space between divs should be 20px.
I want four divs in one row.
Two constraints:
Ideally no flexbox space-between, due to last row looking weird with only two divs.
Adding margin only between inner divs not a good option (unless there’s an easy way to do this for dynamically added content?).
Is there a way to accomplish this?
#outer {
width: 460px;
display: inline-block;
}
.inner {
width: 100px;
height: 100px;
float: left;
}
<div id="outer">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
<div class="inner">4</div>
</div>
Codepen example
Try this. Hope, it will work.
I used the CSS grid. By using grid-template-columns, I have declared how four children elements of outer ID take the same area in a row. After that, I used grid-gap: 20px for giving space between four children block.
#outer {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
}
You can use this code:
.inner {
display: inline-block;
}
.inner:not(:last-child){
margin-right: 20px;
}
<div id="outer">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
<div class="inner">4</div>
</div>
Read a reference here: css-protips
You may need to use nth-child(4n)
.inner {
margin-right: 20px;
}
.inner:nth-child(4n){
margin-right:0px;
}
Codepen: https://codepen.io/abozanona/pen/RwbqmZb
You could use a margin and avoid the last one:
.inner:not(:last-of-type) {
margin-right: 20px;
}
have a css float problem that i'm not sure how to fix or best way to fix and can't seem to find anything in searches. I have a variable amount of items to show inside a div, using a css float left on all the inner boxes (1, 2, and 3 in pic) but the float breaks with variable lines of text. the developer outlines show that because box 1 is larger that box 2, box 3 doesn't float flush left like box 1 which screws up the flow. how do i keep the vertical height of box 1 and box 2 but make box 3 float left where it should be? Doing a float: right; does the same thing but just pushes 3 to the left is div 2 is larger than div 1
This is just an example, there could be a variable number of rows and columns so just doing an Nth div css rule won't work. (the containing div is a variable width based on a few conditions including responsive design)
Almost like i have to have a variable buffer at the bottom of each item in a row to match the height of the tallest one. I also don't want to use a min-height as on rows where the divs are the same height will result in extra white space where there shouldn't be. How would i get the tallest element in a row if the number of columns are variable?
A possible solution is to use the empty clearing div trick but again how do I get the number of divs in a row when columns are variable? I tried to force a nth child::after thing in the example but it didn't work
.item:nth-child(2)::after {
clear: both;
}
Search didn't show anything that works so if anyone has a post that does please let me know.
also have to stick with CSS2 if at all possible due to a bunch of users using older browsers that don't use CSS3
One solution is to use display:inline-block for the figures rather than float:left.
.figure {
display: inline-block;
vertical-align: top;
margin: 2px 1em;
border:1px solid grey;
}
.figcaption {
margin:1em;
}
<div class="section">
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1<br/>Line 2
</div>
</div>
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1
</div>
</div>
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1<br/>Line 2
</div>
</div>
</div>
You need to clear:both the 3rd element actually in this case.
See solution below.
img {
width:50%;
float:left;
}
img:nth-child(3) {
clear: both;
}
<img src="http://via.placeholder.com/350x160">
<img src="http://via.placeholder.com/350x150">
<img src="http://via.placeholder.com/350x150">
If you got some complex example please provide jsfiddle.
that's because your <div>s are styled with "float" and 3rd div has floated to 1st, because 1st is taller than others.
Possible solutions (not including the hardcoding - it's like a deadly sin):
Give equal height to each item in a set
.float {
background-color: #f90;
float: left;
height: 100px;
line-height: 100px;
margin: 10px;
text-align: center;
width: calc(50% - 20px);
}
<div class="float">float 1</div>
<div class="float">float 2</div>
<div class="float">float 3</div>
Use different approach, such as flexbox
.wrapper {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.flex {
background-color: #f90;
height: 100px;
line-height: 100px;
margin: 10px;
text-align: center;
width: calc(50% - 20px);
}
<div class="wrapper">
<div class="flex" style="height: 120px;">flex 1</div>
<div class="flex">flex 2</div>
<div class="flex">flex 3</div>
</div>
TL;DR: codepen here make the items have at least 30px margin-right and no margin in case it is mobile view. Without using what I consider hacky media queries or jQuery. And no horizontal scroll
Why?
I want to use flexbox
following problem:
3 items
for desktop they align in a row. For mobile there is maybe 2, maybe 1. Each one having margin-right: 30px;
now, the last one (of the row, 1, 2 or 3 rows possible) must not have margin-right or at least look as if it does not have a margin. No hacks allowed right. This must be a responsive solution.
this is pretty standard imho:
e.g. desktop:
display 3 items, each with a minimum margin of 30px, or more depending on screen size.
If there is less space, flex-wrap to the next line
on small mobiles:
only show one item per row, but centered without the margin-right: 30px
what did I try?
codepen here
HTML
<div class="row no-gutters my-outer">
<div class="col-12 d-flex justify-content-between flex-wrap">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
CSS
.item{
width: 400px;
height: 400px;
background-color: cornflowerblue;
margin-right: 30px;
margin-top: 30px;
}
.my-outer{
margin-top: -30px;
margin-right: -30px;
xxxxwidth: calc(100% - 30px);
}
negative margin on the parent
the issue is, that it creates a scroll bar
there should be a standard solution for this, no?
using width: calc(100% - 30px); creates other odd issues that are unwanted.
when using overflow-x: hidden on the parent element, you get issues with this:
overflow-x:hidden still can scroll
Since the built-in col-12 rule looks like this
.col-12 {
flex: 0 0 100%;
max-width: 100%;
}
it prevents it from being wider than 100%, which it needs to for the margins to work. So if to remove it, and as the col-12 element is a flex row item, it will need a width if no wrap occurs, or it won't fill the available space in its parent.
Then, when it comes to add margins like that, it is better to add it on the left side of the item, as left margin generally won't cause a scroll to appear, which right margin often does, and the compensation for that margin should be applied on the items parent, not the outer most element.
So in below samples I removed col-12, added a custom rule, my-inner, and used left margin.
Now, for the mobile layout, since there is no way to detect when the items wrap, you either need a media query or a script, and as media query is really not a hack, and there is only one property that needs to be altered, justify-content, this is the cleanest solution.
Updated codepen
Stack snippet
.item{
width: 300px;
height: 300px;
background-color: cornflowerblue;
margin-left: 30px;
margin-top: 30px;
}
.my-inner {
flex-grow: 1;
margin-left: -30px;
margin-top: -30px;
}
#media (max-width: 647px) {
.my-inner {
justify-content: space-around !important;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row no-gutters my-outer">
<div class="d-flex flex-wrap justify-content-between my-inner">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
My personal recommendation though, is to use space-around, which IMHO align the items much nicer w/o a big gap between items, and with making use of one of the pseudo elements one can keep the 3rd item left aligned.
Updated codepen 2
Stack snippet 2
.my-inner::after,
.item{
width: 300px;
height: 300px;
background-color: cornflowerblue;
margin-left: 30px;
margin-top: 30px;
}
.my-inner::after {
content: '';
height: 0;
}
.my-inner {
flex-grow: 1;
margin-left: -30px;
margin-top: -30px;
}
#media (min-width: 960px) {
.my-inner::after {
display: none;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row no-gutters my-outer">
<div class="d-flex flex-wrap justify-content-around my-inner">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Thanks to Toskan, here is the final version they made out of my above sample.
Try this at the bottom of your style sheet.
Use #media to target the device by width.
Use max-width and % width for responsive views
Use last-child to make sure there is no margin
on the last item as oppose to using negative margins
#media (min-width:800px)
{
.item
{
width: 100%;
max-width: 400px;
}
.item:last-child
{
margin-right: 0;
}
.row
{
max-width: 100%;
}
}
#media (max-width:800px)
{
.item
{
width: 100%;
max-width: 400px;
margin: 0 auto;
}
.item:last-child
{
margin-right: 30px;
}
.row
{
max-width: 100%;
}
}
My issue is that I have two (or more) divs of the same class, that need to be spaced from each other. I cannot directly use margins however, as the last or first element would also have the margin applied, which I do not want.
-Green is where I want the space
-Red is where I don't want it
As the only solutions I can think of are complicated / involve hard-coding a value, I am hoping that someone can think of a clever, simple solution to this problem.
Details: Sometimes these divs would be by themselves, and on a rare occasion floated.
Any advice on how above ideas could be better, any new ideas, or just help in general would be greatly appreciated ;)
You can try something like the following:
h1{
margin-bottom:<x>px;
}
div{
margin-bottom:<y>px;
}
div:last-of-type{
margin-bottom:0;
}
or instead of the first h1 rule:
div:first-of-type{
margin-top:<x>px;
}
or even better use the adjacent sibling selector. With the following selector, you could cover your case in one rule:
div + div{
margin-bottom:<y>px;
}
Respectively, h1 + div would control the first div after your header, giving you additional styling options.
If you don't require support for IE6:
h1 {margin-bottom:20px;}
div + div {margin-top:10px;}
The second line adds spacing between divs, but will not add any before the first div or after the last one.
Why not use margin? you can apply all kinds off margins to an element. Not just the whole margin around it.
You should use css classes since this is referencing more than one element and you can use id's for those that you want to be different specifically
i.e:
<style>
.box { height: 50px; background: #0F0; width: 100%; margin-top: 10px; }
#first { margin-top: 20px; }
#second { background: #00F; }
h1.box { background: #F00; margin-bottom: 50px; }
</style>
<h1 class="box">Hello World</h1>
<div class="box" id="first"></div>
<div class="box" id="second"></div>
Here is a jsfiddle example:
http://jsfiddle.net/baXmu/2/
REFERENCE:
http://www.html.net/tutorials/css/lesson10.php
DIVs inherently lack any useful meaning, other than to divide, of course.
Best course of action would be to add a meaningful class name to them, and style their individual margins in CSS.
<h1>Important Title</h1>
<div class="testimonials">...</div>
<div class="footer">...</div>
h1 {margin-bottom: 0.1em;}
div.testimonials {margin-bottom: 0.2em;}
div.footer {margin-bottom: 0;}
A slightly newer solution to this problem is to put the divs in a container that is display: flex or display: grid and to use the gap css property which will only add a space between elements inside the container, but not before/after.
flex solution:
.wrapper {
display: flex;
flex-direction: column;
gap: 20px;
}
header, footer {
background: red;
color: white;
}
<header>header</header>
<div class="wrapper">
<div>section 1</div>
<div>section 2</div>
<div>section 3</div>
</div>
<footer>footer</footer>
grid solution:
.wrapper {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
header, footer {
background: red;
color: white;
}
<header>header</header>
<div class="wrapper">
<div>section 1</div>
<div>section 2</div>
<div>section 3</div>
</div>
<footer>footer</footer>