CSS: display:inline-block and positioning:absolute - css

Please consider the following code:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style type="text/css">
.section {
display: block;
width: 200px;
border: 1px dashed blue;
margin-bottom: 10px;
}
.element-left,
.element-right-a,
.element-right-b {
display: inline-block;
background-color: #ccc;
vertical-align: top;
}
.element-right-a,
.element-right-b {
max-width: 100px;
}
.element-right-b {
position: absolute;
left: 100px;
}
</style>
<title>test</title>
</head>
<body>
<div class="section">
<span class="element-left">some text</span>
<span class="element-right-a">some text</span>
</div>
<div class="section">
<span class="element-left">some text</span>
<span class="element-right-a">some more text to force line wrapping</span>
</div>
<div class="section">
<span class="element-left">some text</span>
<span class="element-right-b">some text</span>
</div>
<div class="section">
<span class="element-left">some text</span>
<span class="element-right-b">some more text to force line wrapping</span>
</div>
<div class="section">
<span class="element-left">some text</span>
<span class="element-right-b">some more text to force line wrapping</span>
</div>
</body>
</html>
The element with absolute positioning apparantly makes the containing box "forget" which height he needs.
I need the absolute positioning inside the "section" box, is there another solution for this?
edit
Using tables is not really an option, I need some sort of "multi-level"/"nested" layout, where the second col is always on the same position:
| some text in first column | some text in 2nd column
| some indented text | 2nd column
| also indented | 2nd col
| even more indent | 2nd column with a lot of text that
| makes it wrap
| text | ...
| blah blah | ...
(of course whithout the "|"s)

When you use position:absolute;, the element is taken out of the normal page flow. Therefore it no longer affects the layout of its container element. So the container element does not take into account its height, so if there's nothing else to set the height, then the container will be zero height.
Additionally, setting display:inline-block; does not make any sense for an element that is position:absolute;. Again, this is because absolute positioning takes the element out of the page flow. This is at odds with inline-block, which only exists to affect how the element fits into the page flow. All elements that are position:absolute; are automatically treated as display:block, since that's the only logical display mode for absolute positioning.
If you need absolute positioning, then the only solution to your height problem is to set the height of the container box.
However, I suspect that you could do without the absolute positioning.
It looks like what you're trying to do is position the second <span> in each block to a fixed position in the block, so that they line up.
This is a classic CSS problem. In the "bad-old-days", web designers would have done it using a table, with fixed widths on the table cells. This obviously isn't the answer for today's web designers, but it is something that causes a lot of questions.
There are a number of ways to do it using CSS.
The easiest is to set both the <span> elements to display:inline-block;, and give them both a fixed width.
eg:
<div class='section'>
<span class="element-left">some text</span>
<span class="element-right">some text</span>
</div>
with the following CSS:
.section span {display:inline-block;}
.element-left {width:200px;}
.element-right {width:150px;}
[EDIT]after question has been updated
Here's how I would achieve what you're asking now:
<div class='section'>
<span class="element-left"><span class='indent-0'>some text</span></span>
<span class="element-right">some text</span>
</div>
<div class='section'>
<span class="element-left"><span class='indent-1'>some text</span></span>
<span class="element-right">some text</span>
</div>
<div class='section'>
<span class="element-left"><span class='indent-2'>some text</span></span>
<span class="element-right">some text</span>
</div>
with the following CSS:
.section span {display:inline-block;}
.element-left {width:200px;}
.indent-1 {padding:10px;}
.indent-2 {padding:20px;}
.element-right {width:150px;}
A small amount of extra markup, but it does achieve the effect you want.

No.
You could position absolutely then have a copy of the element inside the section box with visible: none but absolute positioning by definition makes it a "floating" element that doesn't interact with elements above it.
Assuming your page layout is fixed you could use padding-left: #px; to achieve your goal, as I don't think relative positioning is what you want.
Alternatively, you could use display: table-* to force it to retain a stricter form without affecting the document structure as shown here
However depending on whether you want the cells to be fluid you may need to alter the .section divs into display: table-row if you don't like a predetermined width setup and want the separate .section's to line up.

This can in fact be done easily and simply with divs. You just need to place a div with position:relative inside the inline or block display div. Set its width and height to the same as the containing div. You will then find you can position another div absolutely inside it.

Related

how can I clip an <img> inside a <blockquote>

I am trying to limit the horizontal size of whatever I load in a blockquote (I do not control that content in the blockquote so I know it's going to screw up my layout). Here is a reduced testcase of what the page layout looks like:
<html>
<body>
<div style="width: 800px; background-color: #ff0000;">
<div style="display: table;">
<div style="display: table-row;">
<blockquote style="overflow:hidden;">
<div style="width: 1000px; height: 400px;background-color: #00ff00;"></div>
</blockquote>
</div>
</div>
</div>
</body>
</html>
The size of the blockquote is implicitely set through a width on one of its parent elements and a table container is used to layout the blockquote itself.
Now, if you try to copy/paste the above html into a test.html file, you will see the entire inner div displayed as blue, beyond the boundaries of the red background. I would like to make sure it gets cliped at the background boundaries.
The question is then: is there a way to do this without changing the structure of the html layout and without having to set again an explicit width on the blockquote itself (I cannot do the latter because I do not know the real size of the blockquote in the real layout because there are other elements within the outer div that take an unknown amount of horizontal space) ?
EDIT
Earlier, I naively tried the following. I added an extra column in the table to illustrate the fact that I really do not know how much space the other elements in the table will suck up.
<html>
<body>
<div style="width: 800px; background-color: #ff0000;">
<div style="display: table;">
<div style="display: table-row;">
<div style="display: table-cell;">
<blockquote style="overflow:hidden;" id="inner">
<div style="width: 1000px; height: 400px;background-color: #00ff00;"></div>
</blockquote>
</div>
<div style="display: table-cell;">
<div style="width:100px; background-color:#0000ff; height: 300px;"></div>
</div>
</div>
</div>
</div>
<script>
var width = document.getElementById('inner').parentNode.offsetWidth;
console.log(width);
</script>
</body>
</html>
In order for overflow: hidden; to work you have to set the dimensions of the element explicitly. So, yes, sorry, you have to specify the width on blockquote.
If you are allowed to, you can use javascript to determine the width of the parent element which has a set width and then set the width of the blockquote accordingly.
Here's an example of how that might work, using your current markup:
var root = document.getElementsByTagName('div')[0],
block = document.getElementsByTagName('blockquote'),
i;
for (i = 0; i < block.length; i += 1) {
block[i].style.maxWidth = root.style.width;
}
Demo
However, this would be vastly improved if you were to give the div that's got the set width a class name or id. Check out this fiddle to see how that would work.

Centring a div box when you cannot adjust html

I am trying to adjust the CSS so the "product" and product information is centered and not floated to the left I cannot adjust the HTML as its given via a shortcode thats added into the WP post but maybe I could wrap it in a div?
HTML:
<ul class="products ribbon">
<li class="product last first">
<a href="http://dailybabydeals.co.nz/shop/estella-rose-designs/">
<div class="thumbnail">
<span class="onsale">Sale!</span>
<img width="325" height="325" src="http://dailybabydeals.co.nz/wp-content/uploads/2013/02/Front-Page-325x325.jpg" class="attachment-shop_catalog wp-post-image" alt="Front Page" />
<div class="thumb-shadow"></div>
<strong class="below-thumb">Estella Rose Designs</strong>
</div>
<span class="price"><span class="from">From: </span><del><span class="amount">$25</span></del> <ins><span class="amount">$19.95</span></ins></span>
</a>
<div class="buttons">
Select options</div>
</li></ul>
CSS:
CSS
Okay, let's try this again now that I understand your question better. So you want to center the <ul> element as a whole? That is a lot simpler than what I originally thought you were going for.
To do that, all you need to do is wrap the <ul> element in a span tag that is set to display as an inline-block. Then set the containing element so that its text is centered.
Try this:
<html>
<head>
<style language="text/css">
/*<![CDATA[ */
#test1 {
text-align: center;
}
#test2 {
display: inline-block;
text-align: left;
}
/* ]]> */
</style>
</head>
<body>
<div id="test1">
<span id="test2">
<!-- Place your <ul> element here -->
</span>
</div>
</body>
</html>
how it works
The "test2" element is set to display as an inline-block, which means it displays inline with the text. This means that it can then be affected by properties that manipulate lines of text, such as "text-align".
Setting "text-align" to "center" on the "test1" element makes the inline content -- the "test2" element in this case -- within it become centered on the screen.
The standard way to center a block is to set the "margin-right" and "margin-left" properties to "auto", but that only works for elements that are displayed as blocks and that have a width that is less than 100%.
I would just put it in a div and float it next to another div with nothing in it.
http://www.barelyfitz.com/screencast/html-training/css/positioning/
Like in step 8 in this link.
The reason that it looks like the text "Sale!" is floated to the left is that <img> elements display as inline blocks by default, so the image is on the same line of text as the words "Sale!". A <br /> tag immediately following the text "Sale!" would solve that problem; but you said you can't modify this HTML, right?
Given that restriction, here is how I was able to solve the problem...
Surround the HTML from your example in a <span> tag and assign it a class. I used "test" as my class name".
Then Place this CSS in the head of the HTML document:
<style language="text/css">
/*<![CDATA[ */
.thumbnail img {
display: block;
}
.test {
display: inline-block;
}
.test .price, .test .below-thumb {
display: block;
text-align: center;
}
/* ]]> */
</style>
why it works
The selector for making the image display as a block solves the problem of the missing <br /> tag.
The span tag with which you surrounded the HTML displays as an inline block. This means that it will collapse around its contents, giving you a box within which you can center the text.
Making the items that contain the text display as a block causes them to take a width of 100%, filling the surrounding box
The inclusion of "text-align: center" is what finally makes the text display as centered within its container

why my container div is not as big as the divs inside

I have a CSS question.
<div id="middle">
<div id="middle-left">
<div id="middle-left-top">
MLT
</div>
<div id="middle-left-bottom">
MLB
</div>
<br class="clearFix">
</div>
<div id="middle-right">
MLR
</div>
<br class="clearFix">
</div><!-- #middle-->
the example is at http://jsfiddle.net/Z2yeq/
my questions is why does middle-left not contain the two divs inside?
I want middle-left to expand as middle-left-top and middle-left-bottom
get taller
Thanks for any help
Absoloutely-positioned elements are no longer part of the layout. The parent has no idea how large child items are.
If you want the parent to be as large as the positioned child items to need to calculate and set this using JavaScript.
In general you shouldn't use absolute-positioning for layouts. You should use FLOATS.
The reason it doesn't is because you have it set to position:absolute; Remove position absolute to fix the problem.
#middle-left{
top: 0px;
left: 0px;
width: 800px;
}

How to float image inside of div

I have this html:
<div class="speaker-list">
<div class="view-content">
<div class="views-row views-row-1 views-row-odd views-row-first">
<div class="views-field views-field-title">
<span class="field-content">
Keith Anderson
</span>
</div>
<div class="views-field views-field-field-job-title">
<div class="field-content">VP, Digital Advisory</div>
</div>
<div class="views-field views-field-field-company">
<div class="field-content">RetailNet Group</div>
</div>
<div class="views-field views-field-title-1">
<span class="field-content">
Store of the Future
</span>
</div>
<div class="views-field views-field-field-headshot">
<div class="field-content">
<div id="file-53" class="file file-image file-image-jpeg contextual-links-region">
<div class="content">
<img typeof="foaf:Image" src="/kanderson.jpg" width="180" height="180" alt="" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
It's dynamically generated by a Drupal view, so I can't change the output html at all. I need to work with what is here. Here's the desired result:
Without any styling on the headshot, this is what it looks like:
I tried to style the image to force it to float to the left of the text:
.view-speaker-list div.view-content div.views-row div.views-field
div.field-content div.file-image div.content img {
border: 1px solid #666;
float: left;
position: relative; /* tried with and without position (inc. absolute) */
left: 30px;
}
Obviously I'm doing something wrong, because this is what I get (with relative position):
and with absolute position:
I've also tried putting the float on the "uppermost" div class that holds the image, with no position on the div:
.view-speaker-list div.view-content div.views-row
div.views-field-field-headshot {
float: left;
}
It gives the same result as the position: relative screenshot.
Where am I going wrong? If I had control over the html I'd do it differently, but I'm not sure how to deal with all of these nested divs.
EDITED TO ADD NEW SCREENSHOT FOR #WEX
Here's what it looks like when I tried to use your code with the html reordered - http://jsfiddle.net/mPa7z/
I'll try to explain the "right" way to use float so that you can see why your way didn't work.
In your post, you try to apply float: left to the <div> surrounding your image, but that technique only works when the element you are floating is above all the elements you want to wrap around it. That "may" solve your problem, but that technique has it's pitfalls if you're trying to use it to create two distinct columns - if the text on the right is taller than the floated element, the text on the right will wrap below it. So then you have to add another container around your non-floated elements to ensure that it won't wrap. This solves your problem, but doesn't really help if you can't even edit your markup!
I'd argue that the technique I've posted below works better, and solves your problem: http://jsfiddle.net/Wexcode/AQQwX/
.view-content {
position: relative;
min-height: 180px;
padding: 0 0 0 180px; }
.views-row { padding: 20px 0 0 20px; }
.views-field-field-headshot {
position: absolute;
top: 0;
left: 0; }​
If you have access to the View itself in Drupal, you can reorder the elements. When logged into Drupal, open the View (in Drupal 7: Structure > Views > Viewname), look for "Fields" and click on the triangle next to "add", which will have a popup, then click "rearrange". You can then drag the photo field to be the first item in the View, then adjust your CSS to float the image to the left.
EmmyS,
Instead of trying to get the headshot to float:left, have you considered making the others float:right? This will give the impression that the image is floating left without having to change the markup in any way.
div.speaker-list div.views-row > div.views-field {
float:right;
clear:both;
}
div.speaker-list div.views-row > div.views-field.views-field-field-headshot {
float:none;
clear:none;
}
The above CSS should work with that specific configuration without altering any of your other Drupal generated markup. In order to make sure that other CSS does not interfere, I've applied as much specificity as possible. Since the headshot will be back in the containing <div>, you shouldn't need to alter the size of it unless the store is simply too large (I don't know without looking at your data). Finally the CSS is concise, so you can add any additional styling you need on a per-element basis.
Hope this helps,
FuzzicalLogic
When you can drop somewhere else on the page some code, you can gain control over the HTML by using jQuery. Then you could make modifications to the DOM tree.
But I do not understand why you can not edit the HTML. Isn't Drupal open source? You should be able to find the file using FTP and manipulate it.

Floating divs with fixed top position

I have an HTML "toolbar" containing a number of widgets arranged horizontally. Each item is represented by a div in the source document:
<div id="widget1" />
<div id="widget2" />
<div id="widget3" />
I position the divs using float: left. The problem is that I also want them to be pinned to the top of the toolbar so that they don't wrap around if the user reduces the width of the window. Instead, I just want them to overflow horizontally (with the overflow hidden) so that the behavior is like that of a real toolbar.
In other words, I want something like position: fixed but only for the vertical coordinate. Horizontally they should be positioned one after another in a row. Is there any way to do this with CSS?
Update Here's the real HTML I'm using. The divss with class="row" are the ones that should appear as widgets in the toolbar, arranged horizontally in a single row.
<div class="row" id="titleRow">
<span class="item"> <img src="../images/logo.png" height="26" /> </span>
<span class="item" id="title">Title</span>
<span class="item" id="close" onclick="window.close();"> close </span>
</div>
<div class="row" id="menuRow">
<span class="item"> <ul id="menu"></ul> </span>
</div>
<div class="row" id="searchRow">
</div>
<div class="row" id="pageRow">
<span class="item" id="page-related-data"> Page-related data: </span>
</div>
Rather than float: left; try display: inline-block; vertical-align: top;. Then set white-space: nowrap; and overflow: hidden; on the parent element. See http://jsfiddle.net/rt9sS/1/ for an example.
Note inline-block has some issues. It's white space aware (so white space around elements in the HTML will be visible in the document). It also has limited support in IE6/7, although you can work around that by giving the element layout, e.g. .oldie .widget { display:inline; zoom:1; }. See http://www.quirksmode.org/css/display.html#inlineblock for more.
I know this is an old question, wanted to add a simple jquery answer for those that run across it.
$(window).scroll(function(){
$("#keep-in-place").css("top",$(document).scrollTop()+"px");
});
To make higher or lower on page simply add to $(document).scrollTop()
Works for me

Resources