CSS Absolute position occasionally not respected - html

CSS:
.layers {
position: relative;
height: 500px;
width: 500px;
/* Some -webkit and -moz transformations */
}
.layers > div {
position: absolute;
height: 500px;
width: 500px;
}
.item {
position: absolute;
width: 5px;
height: 5px;
}
HTML:
<article class="someclass">
<section class="layers">
<div style="/* -webkit and -moz transformations */">
<img src='image.png'>
<div class="item" style="/* -webkit and -moz transformations */">test</div>
</div>
</section>
</article>
When loading this page, I get image.png with test on top of it 90% of the time.
(exact position depends on the transformations)
The other 10% of the times I try loading the page, the item div is loaded as if the position is static which causes it not to be on top the the image.
My best guess is that it has something to do with what what gets loaded first, so there might not be an exact answer, but maybe there is something else I'm forgetting here.
Note: I tried this on Chrome and Safari, both the same results.

The inconsistent behaviour is due to two things: one, you've not set the actual position (e.g. top/left) for the .items, and two, your image has no dimensions specified, so its size won't be known by the browser until it's loaded.
Because you haven't specified a position, but have specified absolute positioning, the .item elements are defaulting to the values they would have if they were statically positioned. That is, they'll be directly below the image.
I believe that when you're seeing the .items below the image, that's because the image is in your cache, so the browser knows how big it is on its initial layout run, and sets the static position of the .items below the image.
When you're seeing the .items on top of the image, that's because the browser hasn't worked out how big the image is on its initial layout run (i.e. it's still loading) so it positions the .items as though the image has zero height. Usually, once the image was loaded, the layout would be recalculated, and the .items would move down, but because you've specified their positioning as absolute, I believe the browser is assuming it doesn't need to reposition them, as the image size shouldn't affect their positioning, because they've been taken out of the normal layout flow.
Anyway. Specify an actual position for your absolutely-positioned elements, and everything should start working.

Related

How to make an absolutely positioned element sit outside the scrolling parent but still scroll with it?

I have a scrolling div of small preview images which the user should be able to hover over and see a full size image. I've achieved this by using position: absolute; on the larger images.
This works fine for the first line of previews, but when I scroll down to view the second line, the full size image appears further down the page - where the previews had been before I scrolled to them.
However, if I set the parent to be position: relative; the images are only visible inside the scrolling div - so the user can only see a section of each image at a time and must scroll to see the whole thing.
HTML:
<div class="container">
<div class="preview">
<img class="big">
<img class="small">
</div>
</div>
But with multiple preview divs inside the container div.
CSS:
.container {
width: 300px;
height: 120px;
overflow: auto;
}
.preview {
display: inline-block;
}
.small {
width: 100px;
}
.big {
display: none;
position: absolute;
z-index: 2;
}
.preview:hover .big {
display: block;
}
I've got a fiddle here, using coloured divs instead of images to represent .big and .small : https://jsfiddle.net/jsd8t3gr/3/
Is there anyway I can keep the .big images floating outside the .container div like it does in the first fiddle example (no relative positioning), but also have them move when the container div scrolls, like they do in the second fiddle example (with relative positioning on the .container div)?
Everything I've found so far is related to stopping the images from overflowing the parent, I've not found anything about making that happen on purpose.
EDIT - Using this method without setting container div to have relative position works perfectly in Firefox; it's just a case of getting this to work cross-browser
Without relative position, define top of big so it will be relative to the root. If you don't define top, it will be relative to the parent by default. Which doesn't seem to update on Chrome when you scroll. Nice find!
Working fiddle - https://jsfiddle.net/jsd8t3gr/6/

CSS Align text at bottom of div

I'm trying to align the text 'About' on the bottom of an image. The red line indicated the position in the text I want aligned at the bottom. However, whatever I try gives inconsistent results when I try it on desktop and mobile. It currently works on my laptop, you can see it here http://theoddler.github.io/ (click the image to 'open' the slide.)
This is what the html looks like: (it's hosted at github so I'm using liquid tags)
<div class="slide_title">
<span>{{ include.title }}</span>
</div>
<div class="slide_heading clickable">
<img src="{{ include.image }}" width="100%" alt="{{ include.title }}"/>
</div>
the css:
.slide .slide_title {
font-size: 4.938em;
color: #f8f8f8;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
margin: 0;
pointer-events:none;
position: absolute;
left: 0.000em;
top: 14.188em; /*some default when no javascript is used, otherwise set in js*/
}
.slide .slide_title span {
position: absolute;
bottom: -0.24em;
white-space: nowrap;
text-shadow: 0 0 0.05em #999999;
}
The text is in a div, with css position: absolute, and I position it's div with my image (so the bottom of the div is positioned correctly at the bottom of the image, this is how it should be). However now I'm trying to get the text in the div to be positioned correctly.
All thing I tried gave inconsistent results. It would be positioned perfectly on my desktop, but then have a different offset on mobile.
What I tried (that I can remember, tried a lot):
I tried just giving the div an fixed offset in my script to position it.
I tried changing the height of the div, which move the text as I wanted.
Then I tried placed the text in a span inside the div, and moving the span by setting it's bottom. This is what it currently is, and is the closest I got to it being offset equally everywhere I tried.
I also tried setting vertical-align of the div to bottom, but the text didn't move at all.
Is there a consistent way to align text like this? So it works anywhere?
Thanks!
Note: I'm using jquery to position the div.
The main thing here is to understand what you're dealing with:
what you're asking for is for the baseline of the font to be aligned with the bottom of the parent container,
what you need to realize is that (in your image), the text in the div is positioned correctly
You should be able to achieve what you need by tweaking font-size and line-height and using position: absolute; or position: relative;.
font-size
Your image shows the text is either at or almost at the bottom of the parent div. The reason it's not is that the font-size of an element includes both the ascenders and descenders. You can see this by changing the text to something like "Apropos". You'll then see that the extra bit of space is for the tails of letters like g, j, p, q, and y.
line-height
The other thing that is probably going on is that the line-height for the text is some value greater than 1. You can check this by inspecting the element and finding out of the height (minus padding, borders, and margins) is still greater than the font-size.
You can set the value line-height: 1; to force the lines of text to be exactly the same height as the font-size declaration specifies, but beware that this will cause words to 'collide' when there's more than one line of text.
Mobile -vs- desktop
This leaves the matter of the difference between desktop and mobile. With a thorough understanding of font-size and line-height, you should be able to:
reliably position the text so that the bottom of the text element aligns with the bottom edge of the parent element, and
use position: absolute; or position: relative; to move the element into the precise position you need
This is what you've already been doing. But if it doesn't work across devices, then what is probably happening is that your font-size is different across the different devices. There's more than one reason why this might be true. For example:
your mobile device may have a different base font size than the desktop browser; since the text you're working with is sized in ems, this could be a factor (you've done it right by using ems for the positioning too, but it's possible if a pixel font size at or near the root is different per device that something in the cascade winds up different)
your CSS framework--if any--may adjust font sizes for small screens
I think it's likely that you can solve the problem with some combination of media queries and pixel sizes.
I would try something like the following, and if it doesn't work, then start writing media queries to account for the situations where the size/position is out of the acceptable range (note that if this is being caused by a CSS framework, you should be able to find the media queries it's using and use them yourself):
.slide-title {
/* Substitute your own pixel sizes here */
bottom: -3px
font-size: 16px;
line-height: 1;
position: absolute;
}
Pixel sizes aren't inherently bad, and since virtually everything now allows text to scale, there's usually no reason not to use them if they make things simpler. That said, if you do have a compelling case to use ems, try with pixels first and convert to ems once you've got it working. If it worked in pixels but not in ems, then you'll need to inspect the cascade to see what's different and why.
Try doing this:
<div class='slide_wrapper'>
<div class="slide_title">
<span>{{ include.title }}</span>
</div>
<div class="slide_heading clickable">
<img src="{{ include.image }}" width="100%" alt="{{ include.title }}"/>
</div>
</div>
css:
.slide_wrapper {
position: relative;
}
.slide_title {
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
.slide_heading {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
Then in jquery:
var w = $("slide_heading").width();
var h = $("slide_heading").height();
$(".slide_wrapper").css({width: w, height: h});
$(".slide_title").css({width: w, height: h, line-height: (h - 20px)});
this is untested but I'm pretty sure it should work :/
change the [b]20px[/b] to whatever number of pixels the red-line is from the bottom of the image

How do I make a header that remains in the top at all times?

I want to make a header like http://www.chacha.com (doesn't move, is about that wide and that height, and able to fit divs inside it and also has to be an image)
I am starting off with a blank html document and a blank css page, so there I haven't currently written any code.
I've been trying two days straight to do this now so I would really appreciate any help anyone can provide.
I have gimp so if anyone could also give me image dimensions for a perfect header and perfect background size I would appreciate it even more.
CSS:
#header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 10px;
background: url(yourimage.png) repeat-x;
}
<!--html -->
<div id="header"></div>
That should give you a starting place, I can't tell you more without seeing exactly what the layout's supposed to be.
The CSS property you're looking for is position: fixed which will position the element relative to the viewport. This is good breakdown of positioning: https://developer.mozilla.org/en-US/docs/CSS/position
In this specific case, what you've got is an element with styles roughly along these lines:
#header_id {
position: fixed;
width: 100%;
height: 35px;
}
You don't have to set the height, but unless there is content in the fixed element, it will collapse if there is no height specified. They also appear to have put a drop-shadow on the element toget the neat floating effect.
If you want to have an image inside, you can just put the <img> inside the header element, or use it as the background-image url in the CSS and position it with background-position (see also: https://developer.mozilla.org/en-US/docs/CSS/background-position although the compatability table at the bottom is important if you want to do anything too specific with this property).
You can do this with any block-level element (or any element with display:block set on it). In your example they are using the HTML5 <header> tag; a <div> would work, too, if <header> wasn't appropriate for your page.
I would recommend using the Firebug addon with Firefox (or similar developer consoles with other modern browsers) -- you can right click on an element on the page and select 'Inspect element' from the dropdown menu and get a breakdown of both the markup and styling to see how other websites are constructed. Very useful for when you're browsing the internet and you see something and think, 'that's a neat trick, how does it work?'
FOR FULL WIDTH FIXED HEADER
header {
width:100%;
background:green;
height:60px;
margin:-8px;
position:fixed;
}
FOR NONFULL WIDTH FIXED HEADER
Create a div and set width and height (you can also set it left or right by float:left, float:right)
then in this div put the code above but without margin:-8px; and change the width to the width that your div has.
Here is a test

Converting an img tag to a div tag giving odd height results

I'm certainly no CSS guru, but I am working on a problem where I'd like to make copying of images just slightly more burdensome for users. Sure, they can still easily be retrieved, but this makes it so you can't just drag/drop them on your desktop. Basically, I had a bunch of markup like this:
<img width="400" src="my image.png" class="foo" alt="foo">
Instead, I decided to put this into a background image and change the element to a div:
<div width="400" class="foo">
The problem I have is that the images have a fixed width, but a variable height. This worked excellent when I was using an img tag. It doesn't have the same behavior when I use a div tag. Instead, the CSS is requiring me to force a height property to display anything at all:
This doesn't work
.foo {
display: block;
margin: 0;
padding: 0;
width: 400px;
background-image: url(myimage.png);
/* height: 200px; */
}
This sorta does:
.foo {
display: block;
margin: 0;
padding: 0;
width: 400px;
background-image: url(myimage.png);
height: 200px;
}
The problem is the height for the images are all variable as I mentioned before. So it tiles over and over if I hard code a size. The container can be a placeholder for well over 5,000 images, so setting it by hand won't do it. If I can get this div to behave exactly like the img tag did, the problem is solved.
If you are just trying to prevent people from clicking and drag/dropping, I would say put each img into it's own div with position: relative. Add another div inside that relative div that has the following style:
div.img_box {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: none;
z-index: 9999; /* or anything higher than your img's z-index */
}
That will cover up the image with a transparent div.
That way the image (which is part of your content) is still syntactically correct in the html.
Everybody is of course correct in saying that they have already downloaded the images to their computers just by visiting the site.
If you're trying to prevent users from reusing your content easily, some good methods are to:
1. Use images with lower resolution to limit reuse potential
2. Watermark your images
3. A combination of both, in an image sprite.
Hacking at it will just be ugly, ineffective, and difficult to maintain.
You are just setting the background of the div, you aren't adding an image to the div. The div can be resized to whatever it won't resize to what it's background image is. Just use the tag.
The only thing you could do with CSS is add a height which would work for all images. So if you're images range from 200-250px in height, set the div to 250px. Otherwise, you'll need javascript or server-side scripting to determine the height of the image and set the the CSS.

CSS Rounded Corners Not Working - Why Not?

<div id="main-solutions">
<div id="main-solutions-top-left"></div>
<div id="main-solutions-top-right"></div>
<div id="main-solutions-body">
blah blah blah
</div>
</div>
css
#main-solutions {
}
#main-solutions-top-left {
position: absolute;
top: 0px;
left: 0px;
background: url('../images/Top-Left-Gray-Corner.gif') no-repeat top left;
width: 434px;
height: 15px;
}
#main-solutions-top-right {
position: absolute;
top: 0;
right: 0;
background: url('../images/Top-Right-Gray-Corner.gif') no-repeat top right;
width: 434px;
height: 15px;
}
#main-solutions-body {
background: url('../images/Gray-Gradient.jpg') repeat-x;
}
I'm expecting to see that main-solutions has two absolutely positioned divs at the top left and right with my rounded corner image, and then followed by the body with the gradient, but when I use HTML element browsers, the top-left and top-right div are not appearing at all, very confused, why are those divs being disregarded?
UPDATE (for others confused by answer):
At the root of my issue is I didn't understand that both absolute and relative define a new coordinate system for their contents, in addition to specifying the posision of the element itself. Found a good explanation here:
http://www.w3.org/TR/WD-positioning-970131#Positioned
from section 2.2
Like 'absolute' positioned elements,
'relative'ly positioned define a new
coordinate system for child elements,
with the origin located in the
position where the first child element
is rendered
Far as i'm seeing, the corners should be appearing at the top left and right of the page, since your container div doesn't have a CSS position property. Absolute-positioned elements' positions are relative to the innermost parent that has a position other than static (the default).
Try adding position: relative to the container div's CSS. It works much like the default, but (1) if you want, you can shift the div's position by some amount (which isn't extremely useful here, but still), and (2) since the position's not static anymore, absolute-positioned stuff inside the div should position itself relative to the container, rather than to the body/page.
Also, some browsers won't even display a div that has no content -- so the background for said div might not show. You'll probably want to have something in the divs. Even a single will work.
Have you considered using CSS border-radius to achieve this rather than messing around with images?
border-radius is supported by all browsers except IE, but even IE can be made to work with it with the use of a clever little thing called CSS3Pie.
(plus as a bonus, CSS3Pie also gives IE CSS gradient backgrounds, so you could kill two birds with one stone)