Center div on wrapping (when it doesn't fit on the line) - html

I am trying to create this layout using only CSS:
When title fits:
When title doesn't fit:
The btn on the right should be centered if it wraps.
I tried this:
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block">Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
But obviously, the btn is still on the right after it wraps. Any idea how to center it when it wraps ? And I'd like to avoid javascript.
Fiddle here: http://jsfiddle.net/b7rvhwqg/

Pure CSS solution using a flexbox layout:
Updated Example Here
The trick is to add justify-content: center/flex-wrap: wrap to the parent .container element for horizontal centering. Then adjust the first element's margin-right value to auto in order to prevent the last element from being centered when it's on the same line.
(You may need to resize the browser to see how it adjusts).
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.logo-text {
display: flex;
margin-right: auto;
}
.block {
padding: 5px;
border: 1px solid orange;
}
.center-block {
white-space: nowrap;
margin-right: auto;
}
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is short.</div>
</div>
<div class="block right-block">right-btn</div>
</div>
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is slightly longer than the other one. This title is longer than the other one...</div>
</div>
<div class="block right-block">right-btn</div>
</div>

There is an issue to achieve this via Pure CSS. The div is already having a float and you want to have a "long title" to accommodate that float and at the same time, you want the other right float to jump and become center. This is currently not possible. I believe, you need to consider media queries, but again, that will be a dependent solution, but your title looks like independent of expanding/contracting.

is it ok for you if the title will just fit depending on what width u want?.. for example:
{Logo}Title is toooooooooooooooooooooooooooooooooolong {btn}
it will become like this:
{Logo}Title is tooo... {btn}
it will be cut, then only ". . ." will continue

Flexbox is the most suitable for this task:
<div class="container">
<div class="block logo">Logo</div>
<div class="block title">Title that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
.container {
display: flex;
flex-wrap: wrap;
width: 100%
border: 1px solid grey;
}
.block.logo {
flex-grow: 1;
border: 1px solid orange;
}
.block.title{
flex-grow: 10;
border: 1px solid orange;
}
.right-block {
flex-grow: 1;
border: 1px solid orange;
text-align: center;
}
http://jsfiddle.net/gmrash/7b8w982t/

.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.ellipsis{
text-overflow: ellipsis;
/* Required for text-overflow to do anything */
white-space: nowrap;
overflow: hidden; width: 75%;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block ellipsis">Title that is too long Title that is too long Title that is too long that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
jsFiddle

Related

HTML & CSS, how to center 3 divs inside a div?

I am trying to position 3 div in the center of another div but I'm having issues with the positioning. I tried using verticle-align, and negative margins but nothing seems to be working.
.float-container {
border: 3px solid red;
padding: 250px;
position: relative;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
float: left;
padding: 10px;
border: 2px solid red;
margin: 30px;
vertical-align: middle;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
example for my comment
vertical alignment is not avalaible for floatting elements. Nowdays, for this kind of layout, grid or flex are efficient, flexible and easy to put in action. This is not a float job ;)
.float-container {
border: 3px solid red;
display:flex;
align-items:center;
justify-content:center;
gap:30px;
min-height:500px;
position: relative;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
children only need now to be sized . alignement gap in between them is set from the flex parent. A min-height is given (500px inspirated from your padding 250px)
Remove the float: left; and in its place add display: flex;, justify-content: center;, align-items: center;, flex-direction: row;. For requirements like these, flex and grid are usually much simpler to implement.
.float-container {
display: flex;
padding: 250px;
position: relative;
align-items: center;
border: 3px solid red;
justify-content: center;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
margin: 0 10px;
vertical-align: middle;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
An easy and "modern" way is to use Flexbox if there are no limitations being set as part of a requirement to use float. As an example:
.container {
border: 3px solid red;
padding: 20px;
background-color: lightblue;
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
}
.child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
}
<div class="container">
<div class="child">
Float Column 1
</div>
<div class="child">
Float Column 2
</div>
<div class="child">
Float Column 3
</div>
</div>

Make a responsive layout using flex and css grid

I'm trying to do a responsive layout, I'm not good with css so I need help.
Here is the code:
.container {
outline: 1px solid black;
max-width: 490px;
margin: 0 auto;
}
.columns {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.map {
background-color: cyan;
width: 150px;
min-width: 150px;
height: 150px;
min-height: 150px;
margin-right: 20px;
}
.content {
outline: 1px solid black;
background-color: lightgray;
max-width: 320px;
}
.cards {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.card {
background-color: pink;
outline: 1px solid black;
width: 150px;
height: 70px;
display: inline-block;
}
.card.left {
margin-right: 20px;
}
.texts {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.text {
background-color: gold;
outline: 1px solid black;
width: 150px;
height: 200px;
display: inline-block;
}
.text.left {
margin-right: 20px;
}
<div class="container">
<div class="columns">
<div class="map"></div>
<div class="content">
<div class="cards">
<div class="card left">card #1</div>
<div class="card">card #2</div>
<div class="card left">card #3</div>
<div class="card">card #4</div>
</div>
<div class="texts">
<div class="text left">text #1</div>
<div class="text">text #2</div>
</div>
</div>
</div>
</div>
Basically there are two rows.
The first one contains an element with fixed width and height, and on the right four cards.
The second rows contains only two elements.
Each element of this layout has width 150px.
The code shown above works partially.
The first row is ok, the second one no because the gold elements should stay aligned with the cards so when cards are on the right of el1, contents should below the cards.
It is like if there were to be a hidden element (on the left side of contents) that has the same size as el1.
Also I would like everything to always be centered because now it is only if the window width is > 490px.
This is what I'd like to have:
How can I do that?

Background of div does not scroll with the contents

I have the following snippet of html that forms an X-Y scrollable listbox
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
It's working fine, with one problem, as the user scrolls from left to right, the background of the div seems to get left behind. It's as though the actual div only stretches the width of its parent, and the scrolling/overflow thing is "faked" somehow.
Why is this the case?
How do I address the problem? The behaviour I want is for all the items to appear to be the same width as the largest one.
Try adding a container <div class="items"> around the items set it to display:inline-block.
.items {
display: inline-block;
}
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.items {
display: inline-block;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="items">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
</div>
Explanation: by default a block level element takes 100% width of the container no more than that, however an inline block will expand to content length if available e.g. in a scrollable container.
Also apply .items {min-width: 100%;} in case you want the background to grow full width even with less text in every row.

How do I get an absolutely positioned div with overflow auto to grow to the width of it's contents with white-space set to nowrap?

body {
position: relative;
}
.test {
position: absolute;
top: 10px;
left: 10px;
height: 200px;
border: 1px solid #ccc;
overflow-y: auto;
overflow-x: hidden;
white-space: nowrap;
}
.wrap {
display: inline-block;
}
.item {
padding: 10px;
border-bottom: 1px solid #ccc;
}
.item:last-child {
border-bottom: none;
}
<div class="test">
<div class="wrap">
<div class="item">Some</div>
<div class="item">Larger amount</div>
<div class="item">of text</div>
<div class="item">should go in</div>
<div class="item">these items to prove</div>
<div class="item">that this thing is gonna grow to whatever</div>
<div class="item">to whatever</div>
<div class="item">it needs to</div>
</div>
</div>
The problem is that when the vertical scroll bar appears the absolutely positioned div doesn't grow accordingly and some content on the longest item is cut off. If I take 'overflow-x: hidden' off a horizontal scroll bar appears and that's not what I want either.
When 'white-space: nowrap' is removed everything looks good but I want each item to be one line. Is there any way to have the absolutely positioned div grow according to the width of a 'white-space: nowrap' element?
I think this is what you want
body {
position: relative;
}
.test {
position: absolute;
top: 10px;
left: 10px;
height: 200px;
border: 1px solid #ccc;
overflow-y: auto;
overflow-x: hidden;
white-space: nowrap;
}
.wrap {
display: inline-block;
}
.item {
padding: 10px;
border-bottom: 1px solid #ccc;
padding-right:28px;
}
.item:last-child {
border-bottom: none;
}
<div class="test">
<div class="wrap">
<div class="item">Some</div>
<div class="item">Larger amount</div>
<div class="item">of text</div>
<div class="item">should go in</div>
<div class="item">these items to prove</div>
<div class="item">that this thing is gonna grow to whatever</div>
<div class="item">to whatever</div>
<div class="item">it needs to</div>
</div>
</div>
I added padding-right:28px; to accommodate for the width of the existing padding and the width of the scrollbar.

HTML/CSS Float Left and Top/Bottom without position absolute/fixed

I'm working on my Chemistry application, and I'm struggling with displaying div element how I imagined it could work.
My goal is to have divs floating left as on image: so when hiding red/green div everything stays in order.
Is it even possible without using absolute/fixed positioning? I really need those divs to float left and be aware of each other so I can't solve it by position absolute. I tried experimenting with adding margin, but other div cannot fit into place taken by other element margin.
Thank you for your time spent on reading this post!
Code added:
<div class='container'>
<div class='base-cell'>S</div>
<div class='base-cell'>O</div>
<div class='index-cell'>3</div>
<div class='charge-cell'>2-</div>
</div>
.container{
border: 1px solid red;
height: 1.5em;
text-align: center;
position: relative;
}
.base-cell{
position: relative;
background: red;
height: 1em;
float: left;
margin-top: 0.2em;
font-size: 1em;
border: 1px solid orange;
display: inline-block;
}
.index-cell{
position:relative;
height:0.7em;
margin-top:1.5em;
font-size:0.7em;
display:table;
background: blue;
float:left;
}
.ion-index-cell{
position: relative;
height: 1em;
font-size: 0.7em;
border: 1px solid cyan;
display: table;
background: green;
}
.charge-cell{
height: 1em;
font-size: 0.7em;
border: 1px solid blue;
display: inline-block;
float:left;
}
Edit:
Thank you for your replies, I really don't want to use middle column solution, because of another requirement: sorry for not showing full context before.
As you can see in the picture, all elements flow to the left, and I may need to hide some by using display: none. Thats why I'm looking for parentless solution:
If you flip the diagram on its side then its a lot easier to build using floats. You can use transforms to flip it back up the correct way.
.wrap {
max-width: 100px;
-webkit-transform: rotate(90deg) translate(-170px, -10px);
-moz-transform: rotate(90deg) translate(-170px, -10px);
-ms-transform: rotate(90deg) translate(-170px, -10px);
transform: rotate(90deg) translate(-170px, -10px);
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
overflow: hidden;
}
.block {
height: 40px;
width: 100%;
float: left;
border: 1px solid #000;
box-sizing: border-box;
margin: 10px 0;
}
.block-left {
max-width: 40%;
border-color: #f00;
}
.block-right {
max-width: 40%;
float: right;
border-color: #0f0;
}
<div class="wrap">
<div class="block block-top"></div>
<div class="block block-left"></div>
<div class="block block-right"></div>
<div class="block block-bottom"></div>
</div>
<div class="wrap">
<div class="block block-top"></div>
<div class="block block-right"></div>
<div class="block block-bottom"></div>
</div>
<div class="wrap">
<div class="block block-top"></div>
<div class="block block-left"></div>
<div class="block block-bottom"></div>
</div>
This may help you somewhat. Its very crude html but I believe does what your looking for. It should at least help you in the direction your looking to go.
<div style="height:100%;">
<div style="float:left; width: 33%;">
Content 1
</div>
<div style="float:left; width: 33%;">
<div style="height:50%">
<div>Content 2</div>
</div>
<div style="height:50%;">
<div>Content 3</div>
</div>
</div>
<div style="float:left; width: 33%;">
Content 4
</div>
</div>
From your question, it looks like you just want to use float:left instead of position:absolute which you are using currently and still want to hide the green and red boxes, while keeping all other boxes intact.
This can be achieved by using float:left; on the boxes while setting the opacity:0; on the red and green boxes (also visibility:hidden work).
So I'm not sure how you are handling the mark up but hopefully you are doing it the proper way. It seems like you have a grid-format in place but you are not applying this on the middle column.
What you should be doing is creating three columns and then when necessary, you can hide the middle column. The red and green box can exist within the middle column. This way if you ever say wanted to add those red/green sections in the left or right column, you can easily do that.
I have created an example below. I have also added a class called hide which can apply to the different columns and/or inner boxes. Like I was mentioning above, you should be adding hide to the middle col if you want to hide everything in the middle column. Apply hide to the inner elements if you want to hide one of those.
I do some absolute positioning in the middle column but you don't actually need to do this -- you can change this to float: left and simply set a margin-top for the bottom box.
.col {
float: left;
width: 100px;
height: 200px;
border: 1px solid black;
margin-left: 10px;
position: relative;
}
.inner {
width: 100px;
height: 75px;
margin-left: auto;
margin-right: auto;
position: absolute;
}
.top {
top: 0;
border: 1px solid red;
}
.bottom {
bottom: 0;
border: 1px solid green;
}
.hide {
display: none;
<div class="col left"></div>
<div class="col middle">
<div class="top inner"></div>
<div class="bottom inner"></div>
</div>
<div class="col right"></div>
EDIT: I notice you posted your CSS and you're using display: table. For that I would like to refer you to this link.
shouldiusetablesforlayout.com
EDIT2: I see you updated your question but the overall concept applies. You are still dealing with columns but I guess in your case now, you kind of want those columns in containers.
.col-container {
float: left;
margin-bottom: 10px;
}
.col {
float: left;
width: 100px;
height: 200px;
border: 1px solid black;
margin-left: 10px;
position: relative;
}
.inner {
width: 100px;
height: 75px;
margin-left: auto;
margin-right: auto;
position: absolute;
}
.top {
top: 0;
border: 1px solid red;
}
.bottom {
bottom: 0;
border: 1px solid green;
}
.hide {
display: none;
}
<div class="col-container">
<div class="col left"></div>
<div class="col middle">
<div class="top inner"></div>
<div class="bottom inner hide"></div>
</div>
<div class="col right"></div>
</div>
<div class="col-container">
<div class="col left"></div>
<div class="col middle">
<div class="top inner hide"></div>
<div class="bottom inner"></div>
</div>
<div class="col right"></div>
</div>
<div class="col-container">
<div class="col left"></div>
<div class="col middle">
<div class="top inner"></div>
<div class="bottom inner"></div>
</div>
<div class="col right"></div>
</div>
If you view it in full page, and shrink the window size, you'll see the 3rd col-container to appear on the second line. If you want to make sure it only has two columns or things break at certain points you can adjust for that by either adding clear to certain elements, distinguishing row classes, etc.
I would use flexbox and justify-content: space-between; should be the thing you are asking for.
<article>
<div>left</div>
<div class="content">
<p>top</p>
<p>bottom</p>
</div>
<div>right</div>
</article>
article {
display: flex;
min-height: 10em;
}
article > div {
flex: 1 1 calc(33.3333% - 1em);
margin: 0.5em;
}
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
}
Codepen sample (w/ -prefix-free, styling and as SCSS)
Simple ;)