How to contain bounding box when element wraps on white-space? [duplicate] - html

This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
How to center a flex container but left-align flex items
(9 answers)
Closed 5 years ago.
Given the following example...
/* Custom reset */
html {
margin: 20px 0;
}
body {
margin: 0 50px;
}
h1 {
margin: 0;
}
/* Problem code */
h1 {
background-color: lightblue;
text-align: center;
text-transform: uppercase;
display: flex;
align-items: center;
}
h1::before,
h1::after {
background-color: purple;
content: "";
display: inline-block;
flex: 1 0 auto;
height: 3px;
}
h1::before {
margin-left: -50px;
}
h1::after {
margin-right: -50px;
}
h1>span {
background-color: lightpink;
flex: 0 1 auto;
padding: 0 20px;
}
<h1>
<span>Fooooooooooo & Baaaaaaaaaar</span>
</h1>
When you run the snippet you'll notice a pink box with wrapped text (because it doesn't fit all in one line) and purple lines on the sides, like this:
And this is how it looks when the text doesn't wrap (which is OK and it's what I want):
In the first image there's too much space between the text and the purple lines and I need it to be only 20px, like the second image.
In other "words", I'm looking to achieve this:
(simulated image)
It goes without saying that I need this to work with dynamic content (the text could be anything, have any number of words, short or long). I also need the text to be in a single line if it fits, otherwise multiline and always with 20px max between the purple lines and the text.

If I understand your end goal correctly, you could simply set a fixed width on the <span>. This will ensure that there's the desired amount of 'margin' around the pink box, and it will also work with variable content; if there's too much content to display on the one line, it will simply create more lines. Because the new lines are also constrained by the fixed width, the pink box will still retain the same amount of 'margin':
/* Custom reset */
html {
margin: 20px 0;
}
body {
margin: 0 50px;
}
h1 {
margin: 0;
}
div+div {
margin-top: 20px;
}
/* Problem code */
h1 {
background-color: lightblue;
text-align: center;
text-transform: uppercase;
display: flex;
align-items: center;
}
h1::before,
h1::after {
background-color: purple;
content: "";
display: inline-block;
flex: 1 0 auto;
height: 3px;
}
h1::before {
margin-left: -50px;
}
h1::after {
margin-right: -50px;
}
h1>span {
background-color: lightpink;
flex: 0 1 auto;
padding: 0 20px;
width: 350px;
}
<h1>
<span>Fooooooooooo & Baaaaaaaaaar</span>
</h1>
Obviously the value you would need for the fixed width would depend on the context, but 350px works pretty well for your example.

Related

HTML div goes on next line even though width is 33% [duplicate]

This question already has answers here:
3 inline-block divs with exactly 33% width not fitting in parent
(7 answers)
How to remove the space between inline/inline-block elements?
(41 answers)
How can I show three columns per row?
(4 answers)
Closed last year.
Please help me understand this. Here is my HTML (body)
<body>
<main class="container">
<div class="row">
<div class="col">Sparky</div>
<div class="col">Vegeta</div>
<div class="col">Flufferpants</div>
</div>
</main>
</body>
Here is my CSS
* {
font-size: 25px;
/* box-sizing: border-box; */
}
body {
background-color: gray;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: lightgoldenrodyellow;
}
.row {
background-color: rgb(119, 103, 134);
width: 100%;
}
.col {
display: inline-block;
width: 33%;
height: 200px;
}
I am trying to have the 3 cols be on a single row, evenly spaced apart. I know this is easily done through flexbox, but I wanted to try using the width property manually.
Even when I set each of the col to be width 33%, it still rolls onto the next line. What's going on here?
https://jsfiddle.net/zd29ewb6/
Thanks
use display flex on the row
* {
font-size: 25px;
/* box-sizing: border-box; */
}
body {
background-color: gray;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: lightgoldenrodyellow;
}
.row {
background-color: rgb(119, 103, 134);
width: 100%;
display: flex;
}
.col {
width: 33%;
height: 200px;
}
using inline-block elements there always be a whitespace between the elements and you set your width 33% and adding the width of all the 3 divs its width
gets more then the parents width so it shift the third element to next line. so you can reduce the width of col like this.
.col {
display: inline-block;
width: 30%;
height: 200px;
}

Can I change the height of a content string defined inside :after/before pseudo-elements?

I'm using :after pseudo-element to show the separator for the title for a card like below.
.lock-flag {
font-size: 1em;
}
.lock-flag .lock-icon {
margin-right: 0.5em;
}
.lock-flag .lock-icon:after {
content: "-";
}
.lock-flag .lock-separator::after {
content: "|";
color: #666;
}
<div class="lock-flag">
<span class="lock-icon"></span>
<span class="lock-separator"></span>
</div>
<span class="title">Title</span>
The problem is the separator displays correctly at normal size but when screen resizes, the separator size remains the same though the container size (lock-separator) varies based on the screen size as the font-size for body is getting changed through #media.
Please suggest how to resize the separator size. Is this the right method to have separator placed like this?
EDIT:
As per the comment suggested, changed the element from span to div for block display. Still the problem is same.
As seen below, the expectation is to match the height of the separator to lock icon. The heights of the separator and container varies as per pictures 2 & 3.
My proposal: use ::pseudo on the element which size varies. In this demo, I chose to vary the dimensions of the .media (would be the lock icon in your case) which affects its ::after but it can be switched to be ::before of the text on the right (positioned as left: negative-value;).
As absolute positioning is involved, you've to make sure there's enough space between icon and text where the separator will be displayed.
➡️ Codepen
.parent {
display: inline-flex; /* or flex */
justify-content: space-between;
align-items: center; /* vertical aligning */
height: 100%;
outline: 1px dotted #aaa;
}
.media {
position: relative;
display: block;
width: 2rem;
height: 2rem;
margin-right: 2rem;
background-color: #0888;
}
.media::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: -1.2rem;
display: block;
width: 1px;
/* height: 100%; can replace t:0 b:0 */
border-left: 1px solid #444;
}
.tall {
width: 4rem;
height: 4rem;
}
.title {
margin: 0;
}
section {
margin: 1rem;
}
section:not(:first-child) {
margin-top: 1rem;
}
<section>
<div class="parent">
<span class="media"></span>
<p class="title">Heading</p>
</div>
</section>
<section>
<div class="parent">
<span class="media tall"></span>
<p class="title">Heading</p>
</div>
</section>

Fit 3 elements in the same line

I have 3 elements in HTML as follows:
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>
This should fit in the 100% width of the container (<body> or any other <div>). However the .sidebar is being dropped to the next line. I tried to setup border, margin and padding to 0 with the !important definition (just to test) but the result is the same. How can I fit this 3 elements in the same line keeping the width property?
Thanks in advance for your answers.
As someone else mentioned, the issue is that when using display: inline-block, white-space - even between element tags - is accounted for in rendering. There are a few ways to get around this.
Setting display: table-cell rather than inline-block can work in a simple situation like this; just note that it prevents the blocks from wrapping
You can set font-size:0; on the parent to get rid of the whitespace, but you'll have to reset it on all the direct children.
Unless you have to support pre-IE10 browsers, I'd recommend flexbox here! You may need to add some browser prefixes, but the base would look like this (name your parent element something better than 'parent', though!):
.parent { display: flex; }
.navigation, .sidebar { flex: 1 }
.content { flex: 2 }
What that snippet is saying is "make the children fit, and make .content twice as big as the other two".
Even though you removed the padding, margin, and border, inline elements are actually sensitive to white space in the code itself. Remove that and they line up:
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
* {
margin: 0;
padding: 0;
border: 0;
}
<nav class="navigation">Navigation</nav><section class="content">Section</section><aside class="sidebar">Aside</aside>
When you're using display inline-block, it takes the space in your code as a character(space), so, you have 100% + the space required for 2 characters, you could keep the formatting of your code and ¨remove¨ the space between your containers setting the font-size of the parent to 0
.container{
font-size:0;
}
.container *{
font-size:12px;
}
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<div class="container">
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>
</div>
It's because you're using the style of display:inline-block which will recognize and create a space between element if your code have a space (either space, or new line), so what you need to do is just remove the space like answered by j08691 here
Or you can either remove the spacing by using a comment like this one
.navigation {
display: inline-block;
width: 25%;
}
.content {
display: inline-block;
width: 50%;
}
.sidebar {
display: inline-block;
width: 25%;
}
<nav class="navigation">Navigation</nav><!--
--><section class="content">Section</section><!--
--><aside class="sidebar">Aside</aside>
Or other way around is using the style margin like in this example, the background is used to visualize the size of the the inline-block element only
.navigation {
display: inline-block;
width: 25%;
margin: 0 -0.4em 0 0; background: red;
}
.content {
display: inline-block;
width: 50%;
margin: 0 -0.4em 0 0; background: green;
}
.sidebar {
display: inline-block;
width: 25%;
margin: 0 -0.4em 0 0; background: blue;
}
<nav class="navigation">Navigation</nav>
<section class="content">Section</section>
<aside class="sidebar">Aside</aside>

Left-align one element and center-align another, but have centered element pushed by left element

I am currently using flex and I assume it is necessary, but I am open to all CSS solutions.
I have a bar with some elements on the left. This is done with flex: 0 0 auto; on this element group and flex: 1 1 auto; on an empty element after it.
I need to put another set of elements in the center of this bar (not the center of the remaining space). If the first set of elements weren't there, I could do flex: 1 1 auto on the left and right of the centered element with flex: 0 0 auto;.
But now I need to combine these so the left element stays on the left and the middle element stays in the middle, but I also need the left element to push the middle element to the right (therefore making it no longer centered) if they touch.
Edit: I should mention that the widths of both elements are dynamic. I do know heights, but it would be better not to need them.
Something like this?
HTML
<body>
<aside>Left</aside>
<main>Right</main>
</body>
CSS
* {
margin: 0;
padding: 0;
}
main {
width: 1000px;
height: 500px;
background: cyan;
margin: 0 auto;
}
aside {
float: left;
width: 200px;
height: 500px;
background: magenta;
}
Here's a solution that uses absolute positioning and requires the left block's width to be explicitly set. Essentially, absolute positioning takes the block out of the flow and to make sure that the left and right blocks do not overlap, the left margin is set on the right block that is the size of the left block's width.
Here's a fiddle: http://jsfiddle.net/4RqEr/. (Resize the preview window to see the effect).
HTML:
<div class = "container">
<div>left</div>
<div>Pushed to Right</div>
</div>
CSS:
* {
margin: 0;
padding: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
padding: 10px;
}
.container {
background-color: #ccc;
position: relative;
text-align: center;
overflow: hidden;
}
.container > div:first-child,
.container > div:nth-child(2) {
padding: 10px 20px;
background-color: #fA5858;
color: #fff;
text-transform: uppercase;
font: 15px/1 Sans-Serif;
}
.container > div:first-child {
position: absolute;
left: 0;
width: 100px;
}
.container > div:nth-child(2) {
display: inline-block;
background-color: #5882FA;
margin: 0 100px;
white-space: nowrap;
}

How to use css3 flexbox to create multi-column layout without expanding vertically?

I'm playing with css3's flexbox in Chrome (no need to worry about cross-browser for this). I'm having a hard time convincing it to lay out my content the way I'd like. Here's a sketch of my goal:
Here's a jsFiddle of my attempt: http://jsfiddle.net/Yht4V/2/ This seems to work great except each .group will expand its height rather than create multiple columns.
I'm using flexbox pervasively here. The body lays out vertically, with the #content div taking the remaining height of the page. Each .group is laid out horizontally. Finally, each .item is laid out within a .group vertically with wrapping.
Unfortunately, each .group ends up as a single column by expanding the #content height, which causes a vertical scrollbar (unwanted). If I set the height of each .group to a fixed pixel size, the items break out into multiple columns, but this defeats the fluidity of the flexbox. Here's what it looks like with fixed heights: http://jsfiddle.net/Yht4V/3/
So, how can I get my #content div to not expand vertically since everything is managed with flexboxes without setting a fixed height? I was expecting the flexbox to trigger more columns instead of expanding the height of its parent and causing a scrollbar.
From what I've seen with the Chrome and Opera implementations for Flexbox, a flex-direction of column requires restricting the height of the element, otherwise it will continue expanding vertically. It doesn't have to be a fixed value, it can be a percentage.
That said, the layout you want for your .group elements can also be achieved by using the CSS Columns module. The flow of the elements will be similar to that of the flexbox column orientation, but it will create columns as long as there's enough width for them, regardless of how long the document is.
http://jsfiddle.net/Yht4V/8/ (you'll have to excuse the lack of prefixes)
html {
height: 100%;
}
body {
height: 100%;
display: flex;
flex-flow: column nowrap;
}
h1 {
padding: 1em;
}
#content {
padding: 10px;
background-color: #eee;
display: flex;
flex-grow: 1;
}
#content > .group {
margin: 10px;
padding: 10px;
border: 1px solid #cfcfcf;
background-color: #ddd;
flex: 1 1 auto;
}
#content > .group:first-child {
columns: 10em;
flex-grow: 2;
}
#content > .group .item {
margin: 10px;
padding: 10px;
background-color: #aaa;
break-inside: avoid;
}
#content > .group .item:first-child {
margin-top: 0;
}
Leaving it as a bunch of nested flexboxes, this was about as close as I could get it:
http://jsfiddle.net/Yht4V/9/ (again, no prefixes)
html {
height: 100%;
}
body {
height: 100%;
display: flex;
flex-flow: column nowrap;
}
h1 {
padding: 1em;
}
#content {
padding: 10px;
background-color: #eee;
display: flex;
flex: 1 1 auto;
height: 100%;
width: 100%;
}
#content > .group {
margin: 10px;
padding: 10px;
border: 1px solid #cfcfcf;
background-color: #ddd;
display: flex;
flex-flow: column wrap;
flex: 1 1 30%;
max-height: 100%;
}
#content > .group .item {
margin: 10px;
padding: 10px;
background-color: #aaa;
}
Replace the following in your css -
display: -webkit-flex;
to the following -
display: -webkit-box;
This worked very well for me :-)