I'm quite new to Bootstrap, I'm struggling with the grid system while trying to reproduce the following template:
In this example I have 3 columns:
first columns holds some info/pictures. This column holds a lot of data.
second column holds 3 (but potentially n) contact info (email, address, phone number, ...)
third column holds some random info
I'd like to split the 2nd column into 3 rows, with equal height. What I need to do is to vertically center these 3 rows in the 2nd column, and possibly expand their heights to fill the parent (2nd column) height.
This is an example of what I've achieved till now:
<div class="row container">
<div class="col-md-4 first">
<p> ... VERY LONG CONTENT ... </p></div>
<div class="col-md-4 second">
<div class="row">
Telephone number
</div>
<div class="row">
Address
</div>
<div class="row">
email
</div>
</div>
<div class="col-md-4 third">
Something else, vertically centered
</div>
</div>
Find here a bootply with my code
As an alternative, instead of 3 subrows in the 2nd column, I would also be happy to use a <ul>.
How can I do this? Is there any bootstrap class that I can apply to all 3 rows in order to have them fullfill the parent height?
Thank you in advance
If you are open to use another css library along with bootstrap.You can go ahead with YAML CSS. Which has a good feature for grid system with customization.
What you want can be achieved as follows in yaml.
<div class="ym-grid ym-equalize" style="border:2px solid greenyellow;">
<div class="ym-g33 ym-gl">
<div class="ym-gbox-left" style="border:2px solid red;">
<h6>Left Grid Column</h6>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
<p> ... VERY LONG CONTENT ... </p>
</div>
</div>
<div class="ym-g33 ym-gl">
<div class="ym-gbox-left" style="border:2px solid red;">
<div class="ym-grid" >
<div class="ym-gbox" style="border:2px solid orange;">
<br>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<br>
<br>
</div>
</div>
<div class="ym-grid" >
<div class="ym-gbox" style="border:2px solid orange;">
<br>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<br>
<br>
</div>
</div>
<div class="ym-grid" >
<div class="ym-gbox" style="border:2px solid orange;">
<br>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<br>
<br>
</div>
</div>
</div>
</div>
<div class="ym-g33 ym-gr">
<div class="ym-gbox-right" style="border:2px solid red;">
<h6>Right Grid Column</h6>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren.</p>
</div>
</div>
</div>
Excuse the inline styling ... used for reference. Hope this Helps :)
I have added css styles to hold columns in place as shown in this answer:
.row {
overflow: hidden;
}
[class*="col-"] {
margin-bottom: -99999px;
padding-bottom: 99999px;
}
To fullfill the middle column height I have added javascript which counts the left column height and redistributes it to the middle column rows:
$(".parent").each(function(){
var $children = $(this).children();
$children.height($(".height_parent").height() / $children.length - 2);
});
In HTML parent is class added to the middle column div and height_parent class added to the left column div.
Here is updated bootply.
Try this one
HTML
<div class="container">
<h6>parent row</h6>
<div class="row parent">
<div class="col-md-4 column">
<p style="padding-top: 260px;">Column one</p>
</div>
<div class="col-md-4 column">
<div class="row subRow">
<p>Subrow 1</p>
</div>
<div class="row subRow">
<p>Subrow 2</p>
</div>
<div class="row subRow">
<p>Subrow 3</p>
</div>
</div>
<div class="col-md-4 column">
<p style="padding-top: 260px;">Column Three</p>
</div>
</div>
CSS
.subRow {
color: orange;
border: 3px solid orange;
height: 100px;
padding-left: 5px;
}
.container .parent {
border: 3px solid green;
}
.container {
color: green;
}
.column {
border:3px solid red;
text-align: center;
color: red;
}
I hope it will help someone
/* used this code it's help */
.first{
background: yellow;
display: table-cell;
float:none;
}
.second{
background: white;
display: table-cell;
float:none;
}
.third{
background: orange;
display: table-cell;
float:none;
}
Live Demo
Related
I'm not a designer and haven't done anything much with CSS in quite a while. This is the first time I've had to use flexbox layout, and I'm a little lost.
This is the HTML structure I have to work with... I can't change this.
<section class="infobox">
<main class="popup">
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
This is the CSS I currently have:
<style type="text/css">
/* <![CDATA[ */
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float:left;
padding: 20px 10px 10px 10px;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
width: 50vw;
flex-direction: row;
}
This is how it renders...
I need the footer section to fall below the image in the aside. I've tried various things with align-self and flex-grow (among others) but have not happened upon a working solution. How do I accomplish this?
One approach, as always when dealing with float, is to simply assign clear: both to the element you wish to appear on a new line following the floated element:
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float: left;
padding: 20px 10px 10px 10px;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
width: 50vw;
flex-direction: row;
}
/* forces the selected element(s) to a new line: */
.infofoot {
clear: both;
}
<section class="infobox">
<main class="popup">
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
JS Fiddle demo.
An alternative is to use CSS grid – instead of flex-box – layout:
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float: left;
padding: 20px 10px 10px 10px;
}
.popup {
width: 50vw;
/* using grid layout: */
display: grid;
/* setting a gap between adjacent elements of 0.5em (purely aesthetic,
adjust to your preferences: */
gap: 0.5em;
/* naming the three grid areas; here we define two rows (each quoted
string defines one row) each with two columns, each with named areas.
The first row has an area named 'thumb' and another named 'article',
the second has one area that spans both columns, named 'footer'.
We use the order of the elements in the DOM to place the various
elements appropriately: */
grid-template-areas: "thumb article" "footer footer";
}
.infofoot {
/* in order to see that the .infofoot spans both columns: */
background-color: azure;
/* specifying that the .infofoot element should span two
columns: */
grid-column: span 2;
}
<section class="infobox">
<main class="popup">
<aside class="thumb">
<img class="mini" src="image.jpg">
</aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
JS Fiddle demo.
Further, as a somewhat delayed response, it's entirely possible to use CSS flexbox to lay out these cards, though I prefer to use CSS grid as you're creating a two-dimensional layout (and flex, while responsive and with many use-cases, is typically thought of as a one-dimensional layout). However:
/* a standard, mini, naive reset to reduce browser-default
styles from creating cross-browser layout issues: */
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
display: flex;
flex-direction: row;
/* specifying that the content can wrap to new rows: */
flex-wrap: wrap;
/* assigning a gap between adjacent elements: */
gap: 0.5em;
width: 50vw;
}
.thumb {
/* setting the base-size of the .thumb element to 30% of
its parent's width: */
flex-basis: 30%;
}
/* setting the base-size of the element to 65% of its
parent's width: */
.info {
flex-basis: 65%;
}
.mini {
/* width: 100% causes the <img> element to occupy the full width
of its parent; and object-fit: cover causes the <img> to fully
cover the space available, scaling if necessary but maintaining
its aspect-ratio: */
object-fit: cover;
width: 100%;
}
.infofoot {
background-color: azure;
/* forces the size of the element to occupy 100% of the width of
its parent, taking the 'full' row: */
flex-basis: 100%;
}
<section class="infobox">
<main class="popup">
<aside class="thumb">
<img class="mini" src="https://www.fillmurray.com/200/300">
</aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
References:
clear.
display.
flex-basis.
flex-grow.
flex-shrink.
flex-wrap.
float.
gap.
grid-column.
grid-template-areas.
object-fit.
<section class="infobox">
<main class="popup">//make it flex column
<div >//make it flex row
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse
ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel
facilisis.</p>
</article>
</div>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
In CSS, I can do something like this:
But I've no idea how to change that to something like:
Is this possible with CSS?
If yes, how can I do it without explicitly specifying the height (let the content grow)?
Grid
Nowadays, I prefer grid because it allows keeping all layout declarations on parent and gives you equal width columns by default:
.row {
display: grid;
grid-auto-flow: column;
gap: 5%;
}
.col {
border: solid;
}
<div class="row">
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.</div>
</div>
Flexbox
Use Flexbox if you want children to control column width:
.row {
display: flex;
justify-content: space-between;
}
.col {
flex-basis: 30%;
box-sizing: border-box;
border: solid;
}
<div class="row">
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>
<div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.</div>
</div>
Give overflow: hidden to the container and large (and equal) negative margin and positive padding to columns. Note that this method has some problems, e.g. anchor links won't work within your layout.
Markup
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
CSS
.container {
overflow: hidden;
}
.column {
float: left;
margin-bottom: -10000px;
padding-bottom: 10000px;
}
The Result
Yes.
Here is the completed CSS the article uses. It is well worth reading the entire article, as the author goes step by step into what you need to make this work.
#container3 {
float:left;
width:100%;
background:green;
overflow:hidden;
position:relative;
}
#container2 {
float:left;
width:100%;
background:yellow;
position:relative;
right:30%;
}
#container1 {
float:left;
width:100%;
background:red;
position:relative;
right:40%;
}
#col1 {
float:left;
width:26%;
position:relative;
left:72%;
overflow:hidden;
}
#col2 {
float:left;
width:36%;
position:relative;
left:76%;
overflow:hidden;
}
#col3 {
float:left;
width:26%;
position:relative;
left:80%;
overflow:hidden;
}
This isn't the only method for doing it, but this is probably the most elegant method I've encountered.
There is another site that is done completely in this manner, viewing the source will allow you to see how they did it.
You can do this easily with the following JavaScript:
$(window).load(function() {
var els = $('div.left, div.middle, div.right');
els.height(getTallestHeight(els));
});
function getTallestHeight(elements) {
var tallest = 0, height;
for(i; i < elements.length; i++) {
height = $(elements[i]).height();
if(height > tallest)
tallest = height;
}
return tallest;
};
You could use CSS tables, like so:
<style type='text/css">
.container { display: table; }
.container .row { display: table-row; }
.container .row .panel { display: table-cell; }
</style>
<div class="container">
<div class="row">
<div class="panel">...text...</div>
<div class="panel">...text...</div>
<div class="panel">...text...</div>
</div>
</div>
Modern way to do it: CSS Grid.
HTML:
<div class="container">
<div class="element">{...}</div>
<div class="element">{...}</div>
<div class="element">{...}</div>
</div>
CSS:
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.element {
border: 2px solid #000;
}
Live example is here.
repeat(auto-fit, minmax(200px, 1fr)); part sets columns width. Every column takes 1 fraction of available space, but can't go less than 200px. Instead of shrinking below 200px it wraps below, so it's even responsive. You can also have any number of columns, not just 3. They'll all fit nicely.
If you need exactly 3 columns, use grid-template-columns: repeat(3, 1fr); instead. You can still have more elements, they will wrap, be responsive, but always be placed in 3 column layout.
More on CSS Grid on MDN or css-tricks.
It's clean, readable, maintainable, flexible and also that simple to use!
You ca try it... it works for me and all browser compatible...
<div id="main" style="width:800px; display:table">
<div id="left" style="width:300px; border:1px solid #666; display:table-cell;"></div>
<div id="right" style="width:500px; border:1px solid #666; display:table-cell;"></div>
</div>
Another option is to use a framework that has this solved. Bootstrap currently doesn't have an equal height option but Foundation by Zurb does, and you can see how it works here: http://foundation.zurb.com/sites/docs/v/5.5.3/components/equalizer.html
Here's an example of how you'd use it:
<div class="row" data-equalizer>
<div class="large-6 columns panel" data-equalizer-watch>
</div>
<div class="large-6 columns panel" data-equalizer-watch>
</div>
</div>
Basically they use javascript to check for the tallest element and make the others the same height.
So, if you want just css this would add more code, but if you are already using a framework then they have already solved this.
Happy coding.
Use Flexbox to create equal height columns
* {box-sizing: border-box;}
/* Style Row */
.row {
display: -webkit-flex;
-webkit-flex-wrap: wrap;
display: flex;
flex-wrap: wrap;
}
/* Make the columns stack on top of each other */
.row > .column {
width: 100%;
padding-right: 15px;
padding-left: 15px;
}
/* When Screen width is 400px or more make the columns stack next to each other*/
#media screen and (min-width: 400px) {
.row > .column {
flex: 0 0 33.3333%;
max-width: 33.3333%;
}
}
<div class="row">
<!-- First Column -->
<div class="column" style="background-color: #dc3545;">
<h2>Column 1</h2>
<p>Some Text...</p>
<p>Some Text...</p>
</div>
<!-- Second Column -->
<div class="column" style="background-color: #ffc107;">
<h2>Column 2</h2>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
</div>
<!-- Third Column -->
<div class="column" style="background-color: #007eff;">
<h2>Column 3</h2>
<p>Some Text...</p>
<p>Some Text...</p>
<p>Some Text...</p>
</div>
</div>
Responsive answer:
CSS flexbox is cute, but cutting out IE9 users today is a little insane. On our properties as of Aug 1 2015:
3% IE9
2% IE8
Cutting those out is showing 5% a broken page? Crazy.
Using a media query the way Bootstrap does goes back to IE8 as does display: table/table-cell. So:
http://jsfiddle.net/b9chris/bu6Lejw6/
HTML
<div class=box>
<div class="col col1">Col 1<br/>Col 1</div>
<div class="col col2">Col 2</div>
</div>
CSS
body {
font: 10pt Verdana;
padding: 0;
margin: 0;
}
div.col {
padding: 10px;
}
div.col1 {
background: #8ff;
}
div.col2 {
background: #8f8;
}
#media (min-width: 400px) {
div.box {
display: table;
width: 100%;
}
div.col {
display: table-cell;
width: 50%;
}
}
I used 400px as the switch between columns and a vertical layout in this case, because jsfiddle panes trend pretty small. Mess with the size of that window and you'll see the columns nicely rearrange themselves, including stretching to full height when they need to be columns so their background colors don't get cut off part-way down the page. No crazy padding/margin hacks that crash into later tags on the page, and no tossing of 5% of your visitors to the wolves.
Here is an example I just wrote in SASS with changeable column-gap and column amount (variables):
CSS:
.fauxer * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.fauxer {
overflow: hidden; }
.fauxer > div {
display: table;
border-spacing: 20px;
margin: -20px auto -20px -20px;
width: -webkit-calc(100% + 40px);
width: -moz-calc(100% + 40px);
width: calc(100% + 40px); }
.fauxer > div > div {
display: table-row; }
.fauxer > div > div > div {
display: table-cell;
width: 20%;
padding: 20px;
border: thin solid #000; }
<div class="fauxer">
<div>
<div>
<div>
Lorem column 1
</div>
<div>
Lorem ipsum column 2 dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et
dolore magna aliquyam erat, sed diam voluptua.
</div>
<div>
Lorem column 3
</div>
<div>
Lorem column 4
</div>
<div>
Lorem column 5
</div>
</div>
</div>
</div>
Note: I only found the time to test it in some new browsers. Please test it well before you will use it :)
The editable example in SCSS you can get here: JSfiddle
Please guide me to bring all the "add to basket buttons" in straight line. Currently they are not in proportion.
If anyone can help me with a quick code?
How to align "add to cart" buttons in a straight line in WooCommerce shop page?
The products names (or titles) are embedded in a tag this way:
<h2 class="woocommerce-loop-product__title">Product title</h2>
So you need to define a min-height css rule for that class choosing the biggest height of your product names. So if the biggest product name height is 96 pixels, you will set your rule this way (for example):
.woocommerce-loop-product__title {
min-height: 100px;
/* OR
min-height: 100px !important; */
}
You should add this css rule to the style.css file of your active child theme (or active theme).
You can use flexbox and then the magic margin-top: auto on the button. You can ignore the display: grid on the .items container. It's just for the columns.
.items{
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1em;
}
.item{
display: flex;
flex-direction: column;
}
.item button{
margin-top: auto;
}
<div class="items">
<div class="item">
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. </p>
<button>Add</button>
</div>
<div class="item">
<p>Lorem ipsum dolor sit amet, consetetur </p>
<button>Add</button>
</div>
<div class="item">
<p>Lorem ipsum dolor sit amet </p>
<button>Add</button>
</div>
</div>
More information about flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
I'm using Zurb Foundation, working on an accordion. The Zurb accordion comes with a CSS triangle that acts as a toggler, but I want to use two font-awesome icons instead, depending on whether the li has an active class or not. Right now I'm getting a placeholder for the icon image.
Would prefer to do this with CSS only, if possible.
Here's my CSS:
ul.accordion > li > div.title:after { content:"\f067"; display: block; width: 0;
height: 0; position: absolute; right: 20px; top: 8px;}
ul.accordion > li.active .title:after { content:"\f068"; display: block; width: 0;
height: 0; }
Here's the HTML:
<ul class="accordion">
<li class="active">
<div class="title">
<h5>Accordion Panel 1</h5>
</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</li>
<li>
<div class="title">
<h5>Accordion Panel 1</h5>
</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</li>
</ul>
The CSS shown does not specify the font-family: FontAwesome;. Try adding that.
Looks like it's not a permission issue but in case others come along I am leaving the links.
For localhost changing permissions on the font itself could help: Icon font (#font-face) not rendering on localhost
Or possible cross domain issues with Firefox: http://www.red-team-design.com/firefox-doesnt-allow-cross-domain-fonts-by-default
I want to fit text in a <div> to the width of the <div>, but fit images in the same <div> to the width of the parent <div>
This diagram should make things clear:
(here's the URL if it's too small: http://dl.dropbox.com/u/2792776/screenshots/2012-01-22_1838.png)
I would solve this one of two ways. Here is idea #1:
CSS
#inner {width:400px; position:relative; float:left;}
HTML:
<div id="inner">
<img src="awesomeimage.jpg" alt="this awesome image" />
<p>text goes here</p>
<img src="awesomeimage.jpg" alt="this awesome image" />
</div>
SCRIPT:
<script>
var imgWidth = $(window).outerWidth();
$('#inner > img').css({
width : imgWidth + 'px'
});
</script>
This is assuming you have jQuery loaded up, and that you are using Javascript on your site. If you want to adjust the width of the image, for padding, margins, and borders, do so in the variable.
You can have the image scale with the window, like in the example used in this JS fiddle I created for another question: http://jsfiddle.net/D544n/1/
Idea #2: With Out Javascript.
CSS
#outer {width:100%;} /* Outer becomes irrelevant */
#inner {width:100%;}
#inner img {width:100% !important}
#inner * {width:400px;} /* Set all childs to 400 */
HTML:
<div id="outer">
<div id="inner">
<img src="awesomeimage.jpg" alt="this awesome image" />
<p>text goes here</p>
<img src="awesomeimage.jpg" alt="this awesome image" />
</div>
</div>
The selector for this was grabbed from another S.O. Question.
I don't think you are going to find a clear, simple way to do this. These are my two best ideas, and it could be solved other ways. If you are heading down this path to organize your content, you might want to re-think your strategy at accomplishing your goal.
What if you got rid of the inner div entirely but put a width of 400px on all p tags within the outer div? Then things would flow correctly and the images would be children of the outer div, so they could be limited by its width.
Of course, this could cause some problems if there are a lot of other elements that need to be contained within the 400px area, but if it's just the paragraphs and some headers then you're set.
edit
I refined my approach. I was inspired by Adam Dunn's answer.
All you need to do is wrap each img with a <div class="sanitize">|</div>. Either do it on the server side (recommended) or with a little jQuery wrap call (left for the reader as a homework).
Also don't allow divs only ps.
The secrets are:
Have the border/background in a separate div.border if you need any
Overwrite the max-width to inherit !important
http://jsfiddle.net/HerrSerker/PSPyZ/9/
HTML
<div class="container">
<div class="border"></div>
<div class="inner">
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. .</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut <div class="sanitize">
<img src="http://lorempixel.com/800/200/sports/2" /></div>
</p>
<div class="sanitize"><img src="http://lorempixel.com/800/200/sports/2" /></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>
<br clear="left" />
</div>
CSS
.container {
position: relative;
width: auto;
border: 1px solid red;
}
.container > .inner {
border: 1px solid gold;
width: 100%;
min-width: 400px;
}
.container > .inner > * {
max-width: 400px;
}
.container > .inner .sanitize {
position: relative;
max-width: inherit !important;
border: 1px solid green;
width: 100%;
}
.container > .inner .sanitize > img {
display: block;
width: 100%;
}
.container > .border {
width: 400px;
position: absolute;
top: 1px;
left: 1px;
bottom: 1px;
height: 100%;
border: 1px solid silver;
}
First answer
Why not so?
See here for an example: http://jsfiddle.net/HerrSerker/PSPyZ/
With a little bit of js, you can do this with avoiding all the complication.
$(document).ready(function() {
//read every images
$("img").each(function(k,v) {
//get the width parent's parent
var width = $(this).parent().parent().innerWidth();
//use it
$(this).css('width',width);
});
});
Demo
You can use the CSS overflow property to allow the content to overflow the confines of the container. Try overflow: visible on your inner div.
Expanding on Lazarus' answer:
Set overflow:visible; on your inner div. Then use Javascript to set the max-width of images to the size of your outer div, i.e. the browser viewport. Something like this, maybe?
document.body.innerdiv.img.style.maxWidth = window.innerWidth + 'px';
#outer {position:absolute;top:0;left:1%;width:99%;}
#outer img{width:100%;position:absolute;left:0;}
The best I can thik of are the lines above but they wont wrap the text around cause absolute positioned elements are removed from the flow.
I think ellawren suggested the best solution till now : "got rid of the inner div entirely".
You say: "the contents of the DIV are set by users (and they might not use paragraphs)".
However you can run a simple REGEX pattern before stroring "the contents". The pattern will break text in divs/paragraphs where it is nedeed /before or after image tag/. Then you can style images separately.
Maybe there is some dirty css hack but hacks are never the best way to solve a problem.
HTML
<div class="outer">
<div class="inner"><p>Your content goes here</p>
<img src="http://dl.dropbox.com/u/2792776/screenshots/2012-01-22_1838.png" alt="" />
<p>Your content goes here</p></div>
</div>
CSS
.inner { float: left; width: 400px; overflow: visible; }
.inner img { width: 2000px; }
jQuery
var browserWidth = $(document).width();
$('div.inner img').css('width', browserWidth);
May do like this with pure css.
CSS
.container{
max-width:400px;
border:1px solid red;
}
.container > img {
width: 100%;
position:absolute;
height:200px;
}
img + p{
margin-top:200px;
}
Check this http://jsfiddle.net/PSPyZ/5/
Solution: Float the inner DIV left to make it not as wide as the outer DIV, then set max widths for the inner DIV and it's children.
HTML:
<div id="outer">
<div id="inner">
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
</p>
<img src="image.png" alt="image">
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
</p>
</div>
</div>
CSS:
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#outer {
width: 100%;
height: 100%;
}
#inner {
max-width: 100%;
float: left;
}
#inner > * {
max-width: 400px;
}
#inner > img {
max-width: inherit !important;
}
DEMO: http://pastehtml.com/view/br8c4ht5n.html
(Resizing window shows OP requirements. Gray is outer DIV. Orange is inner DIV. Blue is actual IMG.)
I am sure you have tried this but doesn't this work
Edit:
<script type="text/javascript">
function viewport()
{
var width;
var height;
var e = window,
a = 'inner';
if ( !( 'innerWidth' in window ) )
{
a = 'client';
e = document.documentElement || document.body;
}
width = e[ a+'Width' ];
$('div#inner > img').attr('width', width);
}
</script>
You can read the browser width code from:http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
I just edited a bit and added the jQuery bit
#outer
{
width:100%;
float:left;
}
#inner
{
width:400px;
float:left;
}
<body onload="viewport();">
<div id="outer">
<div id="inner">
Text
<img scr="" />
Text
</div>
</div>
</body>
Example: http://projects.kausweb.com/stack
I am not sure if you wanted javascript thought
I've used the max-width method, in the past, but had to also include a min-width to keep my images from getting too skinny.
Also, if you treat that inner div as a series of content blocks, your document will probably flow a little more intuitively, and you won't need a lot of positioning, etc.
#outer > div { width:400px; border:1px dotted gray; }
#outer > img { max-width:100%; min-width:400px }
<div id="outer">
<div>Inner div block 1 content and whatnot. Inner div block 1 content and whatnot.<div>Nested block within div block 1 with image...<img src="http://jsfiddle.net/img/logo.png"></div></div>
<img src="http://www.alenawooten.com/wp-content/uploads/2012/01/images1.jpg">
<div>Inner div block 2 content and whatnot. Inner div block 2 content and whatnot.<div>Nested block within div block 2 with image...<img src="http://jsfiddle.net/img/logo.png"></div></div>
<img src="http://www.alenawooten.com/wp-content/uploads/2012/01/images1.jpg">
</div>
Here's a jsfiddle: http://jsfiddle.net/B4gKS/
Slide the center divider to see the effect.
I don't think you'll be able to achieve this using pure CSS. Here's an example using a little Javascript.
HTML
<div class="outer">
<div class="inner">
some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text
<img src="http://tinyurl.com/7pl9cw8" />
<p>more text more text more text more text more text more text more text more text more text more text more text more text more text more text more text more text more text more text</p>
</div>
</div>
CSS
.outer {
margin: 40px;
border: 2px solid black;
padding: 10px;
min-width: 404px;
}
.inner {
border: 2px solid black;
width: 400px;
}
JS
function changeWidth() {
var ele = document.getElementsByTagName("img");
var width = (document.getElementsByTagName("div")[0].offsetWidth - 28) + "px";
for(var i = 0; i < ele.length; i++) {
ele[i].style.width = width;
}
}
window.onload = window.onresize = changeWidth;
DEMO
http://jsfiddle.net/XdAPU/