CSS for a text container between min and max width - html

How can I style a DIV with text in it so that if takes the minimum length between a min-width and a max-width?
For example, if I have the min and max set at 200 and 400px, I want:
a div with text shorter than 200px to be 200px wide
a div with text between 200px and 400px to have the width of the text
a div with text longer than 400px to be wrapped
This jsFiddle I made explains it better: http://jsfiddle.net/LHFSn/ ...it sounds simple and straight forward but I just can't seem to figure it out.
And no, the obvious:
min-width: 200px;
max-width: 400px;
...doesn't give me what I want at all.

Setting
display: inline-block
will allow you to achieve the desired result width-wise, but will also mean the elements will be displayed inline, that is, next to one another if they fit.
You can avoid this by wrapping your elements in block-style containers. While this sounds far from ideal it's the first idea off the top of my head that works.
Expanding on your further question, you can float these elements, wrap them in a container that's also displayed inline and then block it using RĂșnar Berg's suggestion of empty blocks.
See sample jsFiddle
Clearfix reference
HTML:
ACTUAL:
<div></div>
<div class="wrapper cf">
<div class="flex-text">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.
</div>
<div class="flex-text">
Lorem ipsum dolor sit amet.
</div>
<div class="flex-text">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</div>
</div>
<div></div>
Further content
CSS:
.flex-text {
min-width: 200px;
max-width: 400px;
display: inline-block;
background: #def;
float: left;
clear: both;
}
/* this is just to show a 200px ruler for reference */
.flex-text:after {
content: "";
display: block;
width: 200px;
border-top: 4px solid black;
margin: 0 0 20px 0;
}
.wrapper {
display: inline-block;
background: lightblue;
}
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}
.cf {
*zoom: 1;
}

You can try to set the container display to table and the inner display to table-cell.
It might get you into more trouble though.
http://jsfiddle.net/fXxV3/3/

Problem:
Your .flex-text is a non-floated block element so by default it fills the width of its parent. In this case, max-width means if your parent is larger then take on the max-width and if your parent is smaller than min-width then take that value.
On the other hand, a floated block element with no width set will shrink to the size of its contents.
Solution:
You basically have to move your min/max width to an outer wrapper div which is not floated as you did, and then float the inner flex-text inside so that the background will only fill the area containing text:
So your markup becomes:
<div class="wrapper">
<div class="flex-text clearfix">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.
</div>
</div>
<div class="wrapper">
<div class="flex-text clearfix">
Lorem ipsum dolor sit amet.
</div>
</div>
<div class="wrapper">
<div class="flex-text clearfix">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</div>
</div>
So your css becomes:
.wrapper{
min-width: 200px;
max-width: 400px;
}
.flex-text {
background: #def;
float:left;
}
Also, since you are floating .flex-text, make sure to add a clearfix.
DEMO

Related

How to make a child div take up all the horizontal space when the parent has overflow: scroll

I want to have a child div with text on one line, with a background color that covers the whole line, inside a parent div with a max-width and be able to scroll along the x-axis.
The background color must be on the child element because the children(there are multiple children) will have different colors. All child elements must have the same width.
I only want to use CSS and no hard coded numbers on the child element.
My problem is that the child element doesn't cover the whole line, you can see the problem when you scroll horizontally.
To reproduce my issue:
.parent {
width: 400px;
max-width: 400px;
overflow: scroll;
}
.child {
white-space: nowrap;
background: skyblue;
}
<div class="parent">
<div class="child">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.
Aenean massa.
</div>
<div class="child">second child</div>
<div class="child">third child</div>
</div>
or https://codepen.io/alawiii521/pen/rNObXrm
You can achieve this by wrapping you text in a span like this and adding the color to span.
.parent {
width: 400px;
max-width: 400px;
overflow: scroll;
}
.child {
white-space: nowrap;
display:table-row;
background: skyblue;
}
<div class="parent">
<div class="child">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.
</div>
<div class="child">second child</div>
<div class="child">third child</div>
</div>
EDIT:
Just add display:table to child class, it will work

Using <p> with left floating divs causes second div to go below first div

https://jsfiddle.net/9nh220q2/1/
Basically, I have something like this:
<div class="container">
<div class="left">
<img src="http://i.imgur.com/bWQUX0O.jpg" class="image" />
<span>0.3 mi</span>
</div>
<div class="right">
<h3>TITLE HERE</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec turpis eu mi nullam sodales.</p>
</div>
</div>
However, these items are inside of a scrolling panel. So, in the jsFiddle I have put these inside of a parent div with width of 600px. As you can see, the <div class="right"> is going below. How can I stop it from doing that?
Calculated width of .right
.right {
width: calc(100% - 120px);
}
.container {
background-color: #fff;
padding: 20px 20px 10px 20px;
overflow: hidden;
border-bottom: 1px solid lightgray;
margin: 0;
}
.left {
width: 100px;
float: left;
margin: 0;
text-align: center;
}
.image {
height: 100px;
width: 100px;
border-radius: 4px;
margin-bottom: 5px;
}
.right {
float: left;
padding-left: 20px;
width: calc(100% - 100px - 20px); /* all width - size of image - padding) */
}
h3 {
margin: 0;
}
<div style="width: 600px">
<div class="container">
<div class="left">
<img src="http://i.imgur.com/bWQUX0O.jpg" class="image" />
<span>0.3 mi</span>
</div>
<div class="right">
<h3>TITLE HERE</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec turpis eu mi nullam sodales.</p>
</div>
</div>
<div class="container">
<div class="left">
<img src="http://i.imgur.com/bWQUX0O.jpg" class="image" />
<span>0.3 mi</span>
</div>
<div class="right">
<h3>TITLE HERE</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec turpis eu mi nullam sodales.</p>
</div>
</div>
<div class="container">
<div class="left">
<img src="http://i.imgur.com/bWQUX0O.jpg" class="image" />
<span>0.3 mi</span>
</div>
<div class="right">
<h3>TITLE HERE</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec turpis eu mi nullam sodales.</p>
</div>
</div>
</div>
You can fix this by removing all float and using flexbox. Flexbox is a powerful modern way to handle this kind of layout. flexboxfroggy is a great way to learn about them.
.container {
display: flex;
justify-content:space-between;
}
Demo
An even better way would be to use standard css grid, but we should wait a bit more.
Edit:
All modern browser support flexbox. For old one, you can use a polyfill if you have to.
You need to set the width of .right to a maximum of 440px. See the working fiddle.
Explanation:
Your container div has a width of 600px. For the elements contained within to line up properly, their widths must add up to a maximum of 600px.
Your img already takes up 100px of that. That means that your div.right can have a maximum width of 500px. (Because 600px - 100px = 500px)
However, if you do set it at 500px, you'll most likely notice that the issue won't be solved. This happens because, by default, most (if not all) browsers render the page using the content-box model which includes the padding and margins of the elements when calculating their widths.
In your case, your containing div has 20px of padding in both sides. In addition, your div.right has 20px of padding on the left. This adds up to 60px which you need to subtract from your available space that we calculated above, 500px. That leaves you with 440px and if you set that as the width of div.right, you'll notice that the elements line up perfectly!
You can also change the default way in which the browser sees the box model by changing the value of box-sizing from content-box to border-box (neither padding nor margins are not calculated in width) or to padding-box (padding is not calculated in width) and then adjust padding, border or width values accordingly.

CSS: two side-by-side p tags, same height, left one fixed-width & known height

I'm trying to get a vertical list of <li>'s of varying height, where each has two <p> tags next to each other and has a height of the tallest <p> tag; the <p> on the left has a fixed width (128px) and the <p> on the right should take up the rest of the page but not wrap underneath the first <p>.
Here's sample HTML:
<ul>
<li> <!-- height = the tallest of the two p tags -->
<p class="category">Something (128px wide)</p>
<p class="description">Something long...
Shouldn't wrap underneath .category
</p>
</li>
<li> <!-- beneath the li above, probably different height -->
<p class="category">Another thing</p>
<p class="description">Another long description...</p>
</li>
</ul>
What should the CSS look like?
Flexbox can do the trick for you.
ul {
width: 300px;
}
li {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
}
li p {
display: inline;
float: left;
background-color: #eeeeee;
}
p.category {
width: 128px;
}
<ul>
<li>
<!-- height = the tallest of the two p tags --->
<p class="category">Something (known width)</p>
<p class="description">Something long... Shouldn't wrap underneath .category
</p>
</li>
<li>
<!-- beneath the li above, probably different height -->
<p class="category">Another thing</p>
<p class="description">Another long description...</p>
</li>
</ul>
More Info:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
There are several ways to skin this cat. If I'm understanding what you're after correctly, I think that using table-row and table-cell display properties may be the easiest way to go.
Here's a jsfiddle:
https://jsfiddle.net/s2jzh31z/2/
That includes the following,
HTML:
<ul>
<li>
<p class="category">Something (known width)</p>
<p class="description">Something long and multiple lines.
Shouldn't wrap underneath category.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.
Lorem ipsum dolor sit amet consecteur adipiscing elit no numi.</p>
</li>
<li>
<p class="category">Another thing(known width)</p>
<p class="description">Something to the right,
determines the height of this "<li>"</p>
</li>
</ul>
CSS:
ul {
margin: 0;
}
li {
clear: both;
display: table-row;
width: 100%;
}
p {
display: table-cell;
padding: .5em;
vertical-align: top;
}
p.category {
width: 128px;
}
I took the liberty of vertical aligning and adjusting the padding a bit to make it look neater. The vertical align was one of the benefits I was looking for in using the table-row / table-cell approach.
To be semantically correct and 'new age' you could do this using CSS3's Flexbox layout but if this is table data (looks to be, using category and description) then you could restructure it as a table (which also helps if you need to support older browsers).
HTML would look like this:
<table>
<tr>
<td class="category">Something (known width)</td>
<td>Something long and multiple lines.sdsdsdsdsdsdsdsdsdsdsdsdddddddddddddddddddddddddddddddsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsssssssssssssssssssssssssssssdddddddddddddddddddddddsdssdsssssssssssssssssssssssssss
Shouldn't wrap underneath .category</td>
</tr>
<tr>
<td class="category">Another (known width)</td>
<td>Another long and multiple lines.
Shouldn't wrap underneath .category</td> </tr>
</table>
and your CSS:
.category {
width: 128px;
}

background image with overlapping content depending on mobile or desktop view

Running into a layout issue between mobile/tablet and desktop.
For mobile: I need the hero image to be first, then the content to be beneath it. (sample here)
For tablet/desktop: I need the content to lay on top of the hero image. (sample here)
I've tried using a background image but found that adjusting the layout of the page effects the background image size and proportions
I've tried absolutely position one on top of the other but run into a scenario where I end up fiddling with the layout between views (using bootstrap) more than what should probably be manageable.
Would love any thoughts on how to produce this result.
Will try to provide code samples of what I've done but not sure it's relevant since none of it seems to produce the desired results.
Here's a quick example that I've created for you, please check:
#container {
background: red;
text-align: center;
padding: 20px 0px;
}
#image, #content {
display: inline-block;
width: 45%;
vertical-align: middle;
}
#image img {
width: 100%;
}
#media (max-width: 500px) {
#image, #content {
display: block;
width: 100%;
}
}
<div id="container"><div id="image"><img src="http://placehold.it/350x150" /></div><div id="content">Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. Lorem ipsum dolor ismet. </div>
Click on Run Code Snippet and view the above snippet in Full Page and then reduce your browser window to 500px or smaller, you'll see that the content will automatically get under the image. Initially, both the <div> containing the image and the content are being displayed as inline-block but for screens smaller than 500px, we use #media-queries to change their display property to block which is why the content goes underneath the image.
Here's a CodePen example I set up to accomplish what you're asking: http://codepen.io/trevanhetzel/pen/pyCnf
Essentially, if you use an inline image as compared to a background image, you can set it's position to absolute at a certain media query breakpoint. With it's container positioned relative and the image's sibling (.hero-content) positioned relative, you can just float it right at that same breakpoint, change the width to however wide you want it, and it sits right on top of the image.
HTML
<div class="hero-contain">
<img src="http://lorempixel.com/1000/300/" class="hero-img">
<div class="hero-content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In a enim eu risus accumsan venenatis. Donec venenatis nunc ac tellus tempor, ac rutrum lorem semper. Suspendisse pulvinar elit sed luctus pulvinar. Donec id ultricies dui. Pellentesque suscipit nulla maximus, mollis urna laoreet, tempor tortor.</p>
</div>
</div>
CSS
.hero-contain {
position: relative;
margin: 0 auto;
max-width: 1000px;
}
.hero-img {
max-width: 100%;
}
.hero-content {
position: relative;
background: rgba(255, 255, 255, .5);
padding: 20px;
}
#media (min-width: 800px) {
.hero-img {
position: absolute;
}
.hero-content {
float: right;
width: 45%;
margin: 20px;
}
}
Use media queries.
When width of window will be less, than your tablet/desktop content, switch media query and just display your divs block. For displaying them in row use display:inline-block;
Example. Try to resize result window.

How do I keep floated elements flopping down without using a fixed width?

I am styling a series of form rows. Each row div has a fixed-width label div, and a content div that can contain any number of float: left elements.
Example markup is:
<div class="Row">
<div class="Label">Label Here</div>
<div class="Content">
<div class="Item">Short Content</div>
</div>
</div>
<div class="Row">
<div class="Label">Label Here</div>
<div class="Content">
<div class="Item">
Long Content ... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris id eros magna. Suspendisse eu diam nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce eu neque massa.
</div>
</div>
</div>
CSS so far is:
.Row {
clear: left;
padding: 10px;
}
.Label {
float: left;
width: 150px;
}
.Content {
float: left;
}
.Content .Item {
float: left;
}
jsfiddle here: http://jsfiddle.net/vVy5J/2/
This looks correct as long as the contents of the content div are not wider than the remaining width in the row. If they are, the content div 'flops' down beneath the label instead and hugs the left edge of the row div: http://screencast.com/t/Iknv98R9
I need long content divs to wrap, but still be against the top of the row and flush with the right edge of the label.
The traditional solution for this is to give the content div a fixed width. But that won't fly here because the row widths vary based on browser window size, etc. and the content div needs to stretch from the right edge of the label div to the right edge of the containing row div.
Requirements: I can alter the markup only within the row div. Contents need to be elements, so text-indent won't work for me. I need to support IE7+
You could put a position:relative; on the Row, position:absolute; on the Label just to take it out of the document flow, then margin-left:150px on the Content (or however wide it's supposed to be).
It won't be good though if there's any chance of the Label being taller than the Content.
You can use simple positioning trick. #row must be relative and content is absolute with left: 150px.
.Row
{
...
position: relative;
}
.Content
{
...
position: absolute;
left: 150px;
}
jsfiddle