clearing nested floats - css

I'm creating a tiled grid of images much like an image gallery with a grid of thumbnails, and I need the images to wrap onto the next row after 3 images. So I'm floating a bunch of divs that each contain an image and then clearing the float manually after three images.
The problem is that I'm working within a rather convoluted existing template that already makes use of float to arrange everything. Clearing the float in my grid scrambles the entire page, presumably because it's clearing every float in page so far. What can I do?
I'm clearing the float using by inserting a blank div. ie:
<div style='clear:right'>
Might one of the other methods for clearing floats work better?

Create a suitable container div (if
you don't already have one)
Set a restrictive width on the
container div - equalling the same
that 3 images takes up.
Allow all images to float - they'll
automatically wrap.
Set the container div with
'overflow: hidden', which will clear
the floats for you.
A simplified version might look like this:
<style>
div#container {
overflow: hidden;
width: 300px;
}
div#container img {
float: left;
width: 100px;
}
</style>
<div id="container">
<img src="" />
<img src="" />
<img src="" />
<img src="" />
<img src="" />
<img src="" />
<img src="" />
<img src="" />
<img src="" />
</div>

If your markup is like so:
div
img
img
img
row break
img
img
img
...
Then you need to add this after every three blocks:
<br class="clear" />
But if your markup is like this:
div
div
img
img
img
div
img
img
img
...
..then you just need to apply the following .clear class to your inner DIVs.
Either way, add this to your stylesheet:
.clear:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html .clear { height: 1%; }
*:first-child+html .clear { min-height: 1px; }
You can use this class for all other elements that contain floats.

If IE >= 8 support is fine for you, you might want to consider using display: table instead of floats. Since you want to display a grid, this the more appropriate way of doing it.
http://www.quirksmode.org/css/display.html#table

I'd try to use display: inline-block; to style the elements containing each image.
Example of HTML code for one container:
<style>
.figure {
display: inline-block;
}
</style>
<div class="figure">
<img src="littlepony.jpg" alt="My cute little pony" width="13" height="37" />
</div>
Now there a few pitfalls using this with IE6, IE7 and Firefox 2:
IE 6 and 7 will only style inline elements that have hasLayout triggered, I mean you'll see inline-block behavior if you do this:
<!--[if lte IE 7]>
.figure {
display: inline;
zoom: 1; /* triggering hasLayout */
}
<![endif]-->
Firefox 2 doesn't understand display: inline-block; so you'll have to precede the latter by another display instruction:
.figure {
display: -moz-inline-stack;
display: inline-block;
}
now Firefox 2 is going to annoy you a bit. First, you must have only one child element in your .figure element, otherwise the children would ... stack. So if you have a legend under your image, insert a div between div.figure and img+p
<div>
<img src="littlepony.jpg" alt="Photo of my cute little pony" width="13" height="37" />
<p>Second child of .figure>div and not .figure</div>
</div>
</div>
Second (still only in Fx2), you'll notice from time to time that you can't anymore neither select text inside the -moz-inline-stack'ed element nor click on links it could contain. The fix is to position the added div relatively:
.figure div {
position: relative;
}
Of course the conditional comment for IE6/7 must occur after regular CSS, otherwise it'll be of little help.
And finally, if no elegant solution works for you, use a TABLE. A simple table with only td and no th. If it occurs that:
IE6 and 7 don't like display: table-sth
your CMS causes problems to what would otherwise work fine on another site
Firefox 3 support for inline-block is of no help
than yes it's better for everybody that you use a table and no half-solution causing problems to half your users ;)

Related

Making <img> responsive when within <a>tag?

I have been using the following css to make my images responsive
img{
max-width: 100%;
height: auto;
}
However it doesn't seem to work when the img is within an <a> tag ie.
<img class="fbicon" src="images/fbicon.png" alt="main">
Why is this and what could be a way around it?
Here is the complete code - (it is responsive on the fiddle but not on the site):
https://jsfiddle.net/bLchqb9u/
use width insted of max-width , find the working fiddel : https://jsfiddle.net/5n4rarrL/
The 100% always applies to the value of the parent element. By default <a> doesn't have a 100% width (it's would just be as big as it's content). You would have to change the behaviour, like this:
<img class="fbicon" src="images/fbicon.png" alt="main">
Demo here:
<div style="width: 300px">
<a href="#" style="max-width:100%">
<img style="width:100%;" src="https://upload.wikimedia.org/wikipedia/commons/1/17/Gustave_Caillebotte_-_Paris_Street%3B_Rainy_Day_-_Google_Art_Project.jpg" alt="main">
</a>
</div>
A percentage in max-width is resolved with respect to the width of the containing block.
Then, the only case where your code may not work is
If the containing block's width depends on this element's width, then
the resulting layout is undefined in CSS 2.1.
That should only happen when the width of the containing block is calculated with the shrink-to-fit algorithm. For example, floats, absolutely positioned or inline-blocks with width: auto.
div {
float: left; /* Shrink-to-fit width, depends on the content */
}
img {
max-width: 100%; /* Depends on the containing block */
height: auto;
}
<div>
<a href="#">
<img src="http://lorempixel.com/1000/200/" />
</a>
</div>
The solution is preventing the containing flock from depending on the content. Make sure it has an explicit width.
div {
float: left;
width: 100%; /* No longer depends on the content */
}
img {
max-width: 100%; /* Depends on the containing block */
height: auto;
}
<div>
<a href="#">
<img src="http://lorempixel.com/1000/200/">
</a>
</div>
You should make the <a> element a block container.
Like this:
a {
display: block;
}
img{
width: 100%;
height: auto;
}
<img class="fbicon" src="https://www.wikipedia.org/portal/wikipedia.org/assets/img/Wikipedia-logo-v2_1x.png" alt="main">
This way the <a> tag will behave as a container and the image will stretch to the size of that.
Tried display and width suggestions, but still the the images were not responsive for some reason (while another img was), even though it worked on jfiddle. Finally, the new srcset came to the rescue,
<img class="fbicon" src="images/fbiconlarge.png"
srcset="images/fbiconlarge.png 1380w,
images/fbiconlarge.png 640w,
images/fbiconlarge.png 320w"
However must say, now its a bit too responsive - ending up too small on the smallest screen. Will post a separate Q. THanks #Oriol, Hasan, Hans, CodeiSir

Using :pseudo selector on img tag on hover [duplicate]

I'm trying to use the :before selector to place an image over another image, but I'm finding that it simply doesn't work to place an image before an img element, only some other element. Specifically, my styles are:
.container
{
position: relative;
display: block;
}
.overlay:before
{
content: url(images/[someimage].png);
position: absolute;
left:-20px;
top: -20px;
}
and I find that this works fine:
<a href="[url]" class="container">
<span class="overlay"/>
<img width="200" src="[url]"/>
</a>
but this does not:
<a href="[url]" class="container">
<img width="200" src="[url]" class="overlay"/>
</a>
I can use a div or p element instead of that span, and the browser correctly overlays my image over the image in the img element, but if I apply the overlay class to the img itself, it doesn't work.
I'd like to get this working because that extra span offends me, but more importantly, I've got about 100 blog posts that I'd like to modify, and I can do this in one go if I could just modify the stylesheet, but if I have to go back and add an extra span element in between the a and img elements, this will be a lot more work.
Unfortunately, most browsers do not support using :after or :before on img tags.
http://lildude.co.uk/after-css-property-for-img-tag
However, it IS possible for you to accomplish what you need with JavaScript/jQuery. Check out this fiddle:
http://jsfiddle.net/xixonia/ahnGT/
$(function() {
$('.target').after('<img src="..." />');
});
Edit:
For the reason why this isn't supported, check out coreyward's answer.
The before and after pseudo-selectors don't insert HTML elements — they insert text before or after the existing content of the targeted element. Because image elements don't contain text or have descendants, neither img:before or img:after will do you any good. This is also the case for elements like <br> and <hr> for the same reason.
I found a way to make this work in pure css:
The I'm just fake content-method
a pure CSS method to enable img:after.
You can check out the CodePen: I'm just fake content or see the source.
Source & Snippet
img {
/* hide the default image */
height:0;
width:0;
/* hide fake content */
font-size:0;
color:transparent;
/* enable absolute position for pseudo elements */
position:relative;
/* and this is just fake content */
content:"I'm just fake content";
}
/* initial absolute position */
img:before,
img:after {
position:absolute;
top:0;
left:0;
}
/* img:before - chrome & others */
img:before {
content:url(http://placekitten.com/g/250/250);
}
/* img:before - firefox */
body:not(:-moz-handler-blocked) img:before {
padding:125px;
background:url(http://placekitten.com/g/250/250) no-repeat;
}
/* img:after */
img:after {
/* width of img:before */
left:250px;
content:url(http://lorempixel.com/350/200/city/1);
}
<img
alt="You are watching the ~ I'm just fake content ~ method"
/>
Browser support
✓ Chrome 10+
✓ Firefox 11+
✓ Opera 9.8+
✓ Safari
No support
⊗ Internet Explorer 8 / 9
Please test in other browsers
Due to the nature of <img> being a replaced element, document styling doesn’t affected it.
To reference it anyway, <picture> provides an ideal, native wrapper that can have pseudo-elements attached to it, like so:
img::after,
picture::after{
content:"\1F63B";
font-size:larger;
margin:-1em;
}
<img src="//placekitten.com/110/80">
<picture>
<img src="//placekitten.com/110/80">
</picture>
Here's another solution using a div container for img while using :hover::after to achieve the effect.
The HTML as follows:
<div id=img_container><img src='' style='height:300px; width:300px;'></img></div>
The CSS as follows:
#img_container {
margin:0;
position:relative;
}
#img_container:hover::after {
content:'';
display:block;
position:absolute;
width:300px;
height:300px;
background:url('');
z-index:1;
top:0;
}
To see it in action, check out the fiddle I've created. Just so you know this is cross browser friendly and there's no need to trick the code with 'fake content'.
The pseudo-elements generated by ::before and ::after are contained by the element's formatting box, and thus don't apply to replaced elements such as img, or to br elements.
https://developer.mozilla.org/en-US/docs/Web/CSS/::after
I think the best way to look at why this doesn't work is that :before and :after insert their content before or after the content within the tag you're applying them to. So it works with divs or spans (or most other tags) because you can put content inside them.
<div>
:before
Content
:after
</div>
However, an img is a self-contained, self-closing tag, and since it has no separate closing tag, you can't put anything inside of it. (That would need to look like <img>Content</img>, but of course that doesn't work.)
I know this is an old topic, but it pops up first on Google, so hopefully this will help others learn.
This one works for me:
html
<ul>
<li> name here </li>
</ul>
CSS
ul li::before {
content: url(../images/check.png);
}
::after may be used to display the fallback image of an image
See the example below, first 2 img tags are point to the broken urls. But the second one displays the fallback image instead of the default broken logo from the browser. However, I'm not sure this's any practical, I find it kind of tricky to get it to work right.
img {
position: relative;
display: inline-block;
width: 300px;
height: 200px;
vertical-align: top;
}
img:not(:first-child)::after {
position: absolute;
left: 0; top: 0; right: 0; bottom: 0;
content: "<" attr(alt) "> NOT FOUND";
border: 1px dashed #999;
background: url(https://cdn.dribbble.com/users/1012566/screenshots/4187820/topic-2.jpg) center/100%;
}
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100x75" alt="logo">
In these cases it is preferable to use the <figure> tag, which allows you to manage the css in an optimal way
This way you can use after just on the figure
Example
<div class="exemple">
<figure>
<img src="img1.jpg"/>
</figure>
<figure>
<img src="img2.jpg"/>
</figure>
</div>
<img> is a replaced element and using :before or :after pseudo-elements on it works if the image fails to load and otherwise it does not work. If you intend to have a fallback in case of image load failure,please refer to https://stackoverflow.com/a/71478688/14204452
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
#image img{
display: inline-block;
max-width: 50%;
}
#image::after {
position: absolute;
top: 0;
content: url('https://img.icons8.com/plasticine/100/000000/about.png');
}
</style>
<title>img before</title>
</head>
<body>
<a id="image" href="">
<img src="https://static.remove.bg/remove-bg-web/5c20d2ecc9ddb1b6c85540a333ec65e2c616dbbd/assets/start-1abfb4fe2980eabfbbaaa4365a0692539f7cd2725f324f904565a9a744f8e214.jpg">
</a>
</body>
</html>
Try this code
.button:after {
content: ""
position: absolute
width: 70px
background-image: url('../../images/frontapp/mid-icon.svg')
display: inline-block
background-size: contain
background-repeat: no-repeat
right: 0
bottom: 0
}
I tried and found a simpler method to do so. Here is the HTML:
<img id="message_icon" src="messages2.png">
<p id="empty_para"></p>
What I did was place an empty <p> tag after my image tag. Now I will use p::before to show the image and position it according to my needs. Here is the CSS:
#empty_para
{
display:inline;
font-size:40;
background:orange;
border:2px solid red;
position:relative;
top:-400px;
left:100px;
}
#empty_para::before
{
content: url('messages.png');
}
Try it.
Try ::after on previous element.
Just give the Image "position: relative" and it will work

Chrome: overflow:auto + margin:auto fails to layout correctly sometimes

I'm trying to layout a page which has anchor elements that I would like on a new line and centered. However these blocks are inside of <p> elements which are beside floating images.
Right:
http://test.sunnysidemarket.ca/right.jpg
Wrong:
http://test.sunnysidemarket.ca/wrong.jpg
So basically I have:
HTML:
<div class="content">
<div>
<img src="..." width="276" height="207" />
</div>
<div class="body">
<p>
...
<a class="mediaset" href="...">Link</a>
</p>
</div>
</div>
CSS:
.content img {
float: right;
}
a.mediaset {
margin: 0 auto;
width: 220px;
display: block;
overflow: auto;
}
Or what you can see in the jsfiddle: http://jsfiddle.net/CVkFw/
The issue is intermittent, sometimes it happens, sometimes it doesn't. What it appears to me to be is a bug in chrome where the overflow and margin properties are calculated but when the floating content loads, sometimes the browser doesn't layout the elements again.
There are ways of solving this using jQuery and modifying my HTML but I would really love to solve this with CSS if at all possible.
My best guess is that this erratic behavior is caused by overflow: visible applied in global.styles.css. The problem:
.node-article .field-name-body,
.node-synced-facebook-content .field-name-body {
overflow: visible;
}
I'm offering this suggestion because when I add this CSS override for overflow: hidden, that component appears to load "more solidly". The fix:
.node-article .field-name-body,
.node-synced-facebook-content .field-name-body {
overflow: hidden;
}
The selector itself might need to be adjusted depending on what it is intended to affect. (I'm obviously not that familiar your page's css code.) Hopefully this points you in the right direction though!

Overflowing anchor not clickable

I have some paragraphs inside a div and some of the words are wrapped in anchor tags.
The paragraphs use white-space: nowrap, which causes them to overflow out of the div's boundaries (which is what I intend to do). Problem is, the overflow is visible but anchors are not clickable.
This is probably by design, but still, does anyone know of a way to make the overflowing anchors clickable?
Thanks in advance!
It's because of your div#rightBox - it contains another div inside of it, which is like this: <div class="verticalPlaceholder"></div>. To fix this, instead of using a vertical placeholder like this, change the HTML and CSS like so:
HTML
<div class="rightBox" id="rightBox">
<div class="facebookLike" id="like">
<iframe scrolling="no" frameborder="0" allowtransparency="true" style="border:none; overflow:hidden; width:100px; height:20px;" src="http://www.facebook.com/plugins/like.php?app_id=174634935928464&href=http%3A%2F%2Fgreat-passage.com%2F%3FphotoId%3D113&send=false&layout=button_count&width=100&show_faces=false&action=like&colorscheme=dark&font=arial&height=20"></iframe>
</div>
<!-- Deleted verticalPlaceholder div -->
</div>
CSS
div.facebookLike {
bottom: 75px; /* ADDED */
display: block;
margin: 6px 0 0;
opacity: 0.5;
position: relative; /* ADDED */
}

Floating elements: two ways of doing it, what is more correct?

I'm just trying to put a div next to the other. I've found 2 different ways. You have them here below. But I don't know what of them is more correct..
<html>
<head>
<style type="text/css">
.jander1{
width: 100px;
height: 100px;
float: left;
border: 5px solid;
}
</style>
</head>
<body>
<div class="jander1">jander1</div>
<div class="jander1">jander1</div>
</body>
</html>
<html>
<head>
<style type="text/css">
.jander1{
width: 100px;
height: 100px;
float: left;
border: 5px solid;
}
.jander2{
width: 100px;
height: 100px;
margin-left:100px;
border: 5px solid;
}
</style>
</head>
<body>
<div id="container">
<div class="jander1">jander1</div>
<div class="jander2">jander2</div>
</body>
</html>
Javi
Floating both is simpler, and means that you don't have to be careful if you add more elements next to the first two. Floating just one is more unusual, more often used when you want actual float effects (like text wrapping around the floated element).
As krs1 said, you'll probably want to use some method to clear your floats. The easiest way is to have a containing element (as in your second example), and to apply either overflow: hidden or overflow: auto to it. This can have side effects (if content from the boxes overflows), but does not complicate your markup.
#container { overflow: hidden; }
#container div { width: 100px; height: 100px; float: left; }
First of all, think about your content. The markup of your content should reflect your content; don't let CSS determine the class attributes you use. The nature of that content also affects what CSS you should be using.
Case 1: Different content in the 2 <div> elements
If we're talking about different content between the two <div> elements, such as an image and some text...
<div class="profile-picture"><img src="http://www.gravatar.com/avatar/0be84773790974af8d6a1d5d55801736?s=128&d=identicon&r=PG" alt="Profile picture for Richard" class="" /></div>
<div class="about-me">My name is Richard and I work as a software developer!</div>
... use different classes. The neither is a jander so don't include jargon class attributes to accomodate your CSS. Class attributes are element identifiers and should make semantic sense.
Case 1.1: The Left <div> has a fixed width
Once you get to your CSS, in a case like this one, the image has a fixed width which probably isn't subject to a lot of change; as such you can use technique #2 from your question to give the second <div> a margin-left:
.profile-picture {
width:80px;
height:80px;
float:left;
}
.about-me {
margin-left:81px;
}
Here is a JsFiddle example.
Case 1.2: The Left <div> has a variable width
But what if we need that image to some times be bigger, sometimes be small? What if we don't have knowledge of the image's size when we're writing our CSS?
<div class="profile-picture"><img src="http://media03.linkedin.com/mpr/mpr/shrink_80_80/p/1/000/09a/108/11e3bdd.jpg" alt="Profile picture for Richard" class="" /></div>
<div class="about-me">My name is Richard and I work as a software developer!<br />blah<br />blah<br />blah<br />blah<br />blah</div>
<div class="profile-picture"><img src="http://www.gravatar.com/avatar/0be84773790974af8d6a1d5d55801736?s=128&d=identicon&r=PG" alt="Profile picture for Richard" class="" /></div>
<div class="about-me">My name is Richard and I work as a software developer!<br />blah<br />blah<br />blah<br />blah<br />blah</div>
... one of those images is 128px tall and the other is 80px tall.
We can then float the first <div> while simply targeting the other with anoverflow-x:hidden;`:
.profile-picture {
float:left;
}
.about-me {
overflow-x:hidden;
}
Here is another JsFiddle example.
Case 2: Similar content in the 2 <div> elements
Then by all means give them the same class attributes!
<div>
<div class="column">Here is content for column 1!</div>
<div class="column">Here is content for column 2!</div>
</div>
If they are supposed to behave identically, target them with the same rules and float them both to the left. If they don't behave identically, you can generalize the considerations above; do you know how wide that first <div> should be? If so, go ahead and use the margin-left. Otherwise use overflow-x.
If they work, they work. Option 1 looks good, I've run similar patterns before.
However you're going to run into issues if you attempt to put a block element beneath floating elements. After the second 'jander' class element add this:
<div style="clear:both"></div>
Since both div share styling, I would go with the first example. I would also add a clear:both to your #container since it is wrapping the two divs which are floating left.
Since you have a margin-left in your 2nd div only, I would either use a pseudo-class like #container div:first-child or an id/class to add the margin.

Resources