CSS Align text at bottom of div - html

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

Related

how to make a button responsive which is placed on the image in html?

I have a banner-image, on that image I've placed a link. This page is not getting aligned properly when I zoom-in or zoom-out the browser window or when I resize it.
The link is not getting aligned properly with respect to the image as it was showing in the default view(100% zoom ).
How to make this link responsive? I want the Read More button to be aligned exactly below the text Driving Value creation with ..... text, and the Read More link to be responsive with respect to the image on which it is present. How can I do that?
Here's my JSFiddle
<p class="homeImageLink">
<span>Read More</span>
</p>
Please help.
I am not sure this will work, but I think it would:
.image_container span
{
margin-left:-100px;
}
DEMO
DEMO1
You need to tweak your css so that the positioning is a bit more clear, I've fixed it somewhat here.
The important parts are here:
.image_container {
position: relative;
}
.homeImageLink {
position: absolute;
bottom: 10%;
right: 3%;
}
On the container, position: relative; means that any internal positioning will work from this container. Any positioning apart from static would do here and it's important no intermediate elements in the tree have position set or it will work from that element instead.
The the link container itself is position: absolute; with % values used to keep it proportional to the size of the container. Note also that right is used instead of left so the element appears relative to the right of the container. Now it will never go off the right hand side of the image.
To make this clearer I've removed all the other css from the example and as you can see it still demonstrates the effect you desire.

CSS Absolute position occasionally not respected

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.

how to set button background such that it takes up height and width of parent div? what css property affects which dimension?

please check out the codes first:
html:
<!DOCTYPE html>
<html>
<head>
<title>hello</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div id="container">
<div id="menu">
HOME
</div>
</div>
</body>
</html>
css:
#container
{
width: 80%;
margin: auto;
height: 450px;
}
#menu
{
background-color: #1b9359;
height: 25%;
}
.button
{
text-decoration: none;
float: left;
font: bold 1.2em sans-serif;
line-height: 115px;
margin-left: 20px;
display: block;
text-align: center;
}
.button:hover
{
background-color: #2cd282;
}
so what i would like to acheive is that when i hover to the home button, the whole div changes color, and does not get distorted or mispositioned on zoom. one answer told me that i could use display: block, but that it does not work as you can see. however, i did manage to make it work with display: block when the menu pane is like a vertical column and not a horizontal one. could anyone pls explain why this happens, and how display property of css affects that element? and how to achieve the full highlight without zoom distortion?
If you use percentages as your height and/or width then it will be a percentage of the parent container.
If you want your page to behave well when using a zoom, ie. ctrl + mouse wheel up or down, size everything in your page using em. 1 em = 16px by default. Just get used to using em. Get a calculator out and start converting things. Trust me, it's worth it to have a page that zooms straight in in out without jumbling.
Your outermost container may use percentages as long as you're using an auto margin for the central contents this is an exception to using em, that way things will still be centered on all resolutions. When I say outermost container, I mean body...
Before I tell you how to make it work I'll answer the other questions:
"...I did manage to make it work with display: block when the menu
pane is like a vertical column and not a horizontal one. Could anyone
pls explain why this happens, and how display property of css affects
that element?"
Block elements stack on top of each other vertically. This means that in a vertical arrangement if the zoom level is changed, those elements are perfectly at home taking that extra space up to the right side. Now, if they are intended to be lined up horizontally, display block will not work because that is simply just not what it does. Display inline-block will stack them horizontally preserving heights and widths set for the container, and to my own dismay, adding tiny margins between elements unlike the use of float, which would be touching the previous element, but float is definitely not something I would recommend for a nav menu.
Let's say you have your first link, and it is display:block. It will start its own new horizontal line, assuming there is not a float:(side) item before it with extra space to fill. In that case, you would add clear:both(or :left/:right) to overcome this. Now let's say you want to add a second link to the right of the first one which is display:block. The second one could be display:inline-block, and it would be on the same level as the first one, but if you did this the other way around, the second one, which is display:block, would start on its own new line below.
Now, to make your button do what you want it to do:
I will assume for the purpose of giving you a good answer that screen width in pixels is 1280px. So 80% of that is 64em. That is (1280px * .80)/16px = 64em because 1em = 16px. As I mentioned before, we do this to make your site elastic when it zooms.
You've previously designated #container as height:450px; So let's convert that. 450px/16px = 28.125em (em values can go to three decimal places, but no more) This is good, so we have an exact conversion, and not a rounded value.
container is now finished and should be as such:
#container
{
width: 64em;
margin: auto;
height: 28.125em;
}
Next change height in #menu. You have it as height:25%. That is 25% of 450px/or/28.125em If we leave it at 25% it will mess up the zooming. So let's convert. 28.125em/4 = 7.03125em
This time we must round to 3 decimal places. So we get 7.031em.
menu is now finished and should be as such:
#menu
{
background-color: #1b9359;
height: 7.031em;
}
Next is your button class.
.button
{
text-decoration: none;
float: left;
font: bold 1.2em sans-serif;
line-height: 115px;
margin-left: 20px;
display: block;
text-align: center;
}
At this point I lose some of my own certainty about how CSS will react, but I will start with this. Do not use float:left and Display:anything together. In this case, use display:inline-block. Get rid of the float:left. I am not sure why you have a line-height set. I am guessing it is your way of attempting to set a height for your button because it is 2.5px larger than the height of #menu (line-height of .button = 115px, height of #menu = 112.5px which we have already converted to 7.031em). If that's what you're trying to do you're doing it wrong. get rid of line height, and make it the same height as its container so that it fills it. height:7.031em;
I'll assume if you're making a horizontal menu, that you aren't trying to make one button take up the entire width. If you do not give it a width, it will fill the whole row. I'll be bold and guess you probably want your button somewhere in the ballpark of twice as wide as it is high. Let's just go with 15em(240px). width:15em;
Last is margin-left... 20/16 = 1.25em. Cake.
Now we have:
.button
{
text-decoration: none;
font: bold 1.2em sans-serif;
height: 7.031em;
width:15em;
margin-left: 1.25em;
display: inline-block;
text-align: center;
}
Keep in mind that block elements, whether inline or not, have little built-in margins on top of the margin-left that you've added.
If you make these changes, your page should zoom beautifully and your link will fill out its container vertically, but be a specified width to keep it clean. Never use px or percentages if you want to avoid zoom slop. The body container is 100% by default, but it holds everything and therefore the things in the center seem to grow outward toward the edges and therefore do not show any visible effect from the body not being set based on em, and it also makes the page naturally friendly with a variety of screen resolutions.
I hope this helps.
Edit:
As I mentioned, I lost some of my certainty. The line:
font: bold 1.2em sans-serif;
Does something that makes the container be larger than 7.031em removing that line fixes the problem, but I do not know the remedy if you insist on a font size of 1.2em. I tried setting height to 6.831em instead of 7.031em and it did not do the trick.
A few more tips:
1) If you still feel that you need a margin, perhaps margin-right would better suit you so you don't have random slack space to the left.
2) The CSS I provided does not adjust for the vertical alignment of your link text; to fix it add line-height:7.031em; to the .button class. Note: this method only words with single lines of text!!!

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)

Placing an background image with padding in h2 tag

I want to create a headline (h2) with an image at the right-most area of the bounding box. I have the layout almost right except I can't push the image a little bit to the right of the element's bounding box -- how would I tweak my css so it is displayed correctly?
I'm trying to do something like this:
[{someHeadLineText}{dynamic space }{image}{5px space}]
where the [] indicate the total available width of my content.
Html:
<div class="primaryHeader">
<h2>News</h2>
</div>
Css:
.primaryHeader h2 {
background-color: green; /* the header looks like a box */
color: black;
background: transparent url(../images/edit.png) no-repeat right center;
border: 1px solid red;
}
I am placing the image to the right of my h2 element and centered vertically -- but how do I adjust the placement of the background image?
I'm afraid I think you can't. You can use either right or a pixel value as the image's x-position but that pixel value will always be relative to the left corner of the bounding box. Adding padding won't help either, it will just extend the bounding box further.
The only solution I know for this is either adding the shift to the image itself, or using an absolutely positioned element (with a slight offset) hovering behind the element - but that would require you know the width and height in advance.
Edit: evil, hacky idea. I have no time to try this out right now, but it should work if the h2 is a display: block.
Give the h2 a position: relative.
Place a div or other element inside the h2 with the following:
position: absolute;
left: 0px;
top: 0px;
right: 5px; /* This is the shift */
bottom: 0px;
background-image: url(...);
background-position: right center;
background-repeat: no-repeat;
z-index: -1; /* I don't know whether this will overwrite the h2's content */
this could lead to the desired effect, I'm not sure as I have not tried.
The element may overlay the h2's other content, in which case you would have to put the rest into a <span> element with position: relative and z-index: 1.
It's really hacky. Better put the padding into the image itself, much cleaner.
Can you add padding pixels in the image itself?
You could ditch the background image and use an image instead.
<div class="primaryHeader" style="padding-right: 5px;">
<img src="../images/edit.png" alt="" style="float: right;" />
<h2>News</h2>
</div>
You can look into CSS3 background positioning. It works in all the modern browsers (not IE, of course).