CSS image centering within centered container gives unpredictable results - html

For a while I was stumped my centered background images were not pixel-perfect aligned in their containers. I even got different results within the same browser but different windows
Finally I found out what is happening, but I'm still short of a robust cross-browser solution.
The case: I'm working on a collapsable tree-view in javascript. Everything is functioning alright, but in some cases the collapse/expand buttons are off one pixel to the left.
The images for these buttons are user-definable, as well as the size (width) of the container they appear in. The images are drawn in the center of these containers with background-position: center center;. Now there are cases the image can't be fit exactly in the center of the container (for example, centering a 9px image in a 20px container, there's a 1-pixel difference on either side). This should be no problem, as long as we have consistent behaviour on how the browser handles this.
But here's where it gets messy: I've implemented this tree-view inside a wrapper centered with margin:0 auto; based on the browsers viewport. And here is when I get different results when both the viewport centering and background centering don't fit exactly within the pixel boundaries.
This is probably hard to follow, so I've squeezed the problem into a fiddle: http://jsfiddle.net/3y65wgu8/1/
CSS:
#wrapper1 {
width:400px;
}
#inner1 { /* perfect center */
margin:0 auto;
width:200px;
height:50px;
}
#wrapper2 {
width:399px;
}
#inner2 { /* 1px-offcenter */
margin:0 auto;
width:200px;
height:50px;
}
#container { /* image 1px-offcenter (9px centered in 12px container) */
width:12px;
height:12px;
background:url(data:image/gif;base64,R0lGODlhCQAJALMAANLNve/s58a7rd7Vznuatf////f39wAAALXD1vfz7+fj3tbTxsa6pdbPxt7b0sa2pSH5BAAAAAAALAAAAAAJAAkAAAQoEJFJiSw4l6mxmUYYJgp4nKczJUngKsOkOMOyNMAECALDPAJLhYKIAAA7) no-repeat center center #444;
}
HTML:
<div id="wrapper1">
<div id="inner1">
<div id="container"></div>
</div>
</div>
<div id="wrapper2">
<div id="inner2">
<div id="container"></div>
</div>
</div>
Two different wrappers centering their content, containing two identical containers having a small button drawn as background. Chrome seems to be the only browser that draws the buttons in alignment consistently, but firefox and IE show the problem I described. Try resizing your browser window, and see the buttons bounce from one side to the other.
My question is: how can I get at least identical results, without losing flexibility on button/container/wrapper sizing and styling.
EDIT: Here's a picture that illustrates my use-case:
Example
The area marked in blue is the container that holds the collapse button. This area is always square, but may vary in size. The button can be any image smaller than this container and is placed directly on top where the lines meet. No stretching or scaling should occur on the image. In this example the button is too far to the left. Resizing my browser window makes the image jump in and out of correct alignment, as the fiddle above describes.

There seems to be no way around this than to resize the image container when the image inside can't be centered pixel-perfect, to have consistent cross-browser behaviour on the positioning. Therefore I need to fetch the image meta-data either server-side or client-side.
Server-side (1):
Using getimagesize and getimagesizefromstring and was obviously the way to go. But then I bumped into a problem in my current use-case: the tree is rendered using AJAX, and the relative URL for the image is not relative to the location of the AJAX script.
Issues:
So, for this to work I either have to pass both URL and absolute PATH (or absolute path alone, and have the URL figured out by stripping $_SERVER['DOCUMENT_ROOT'] from it). This approach seems counter-intuitive and restrictive on the developer's part trying to implement this tree module. So I abandoned this idea.
Server-side (2):
Ask for the image dimensions at design time. Plain and simple, place the responsibility at the implementer.
Issues:
Not very elegant, but it works :). (solution 1)
Client-side:
I've but both images inside a hidden DIV, and I fetch the size of the image from the onload event. If by this data the images used inside the containers appear off-center ( image.width%2 != container.width%2 , image.height%2 != container.height%2 ), I loop through these containers and resize them by one pixel in either width or height.
Issues:
I don't like the idea of using hidden elements with triggers for the sole purpose of working around this positioning problem. However, it provides a solid cross-browser solution. The only downside is that there seems to be a slight delay before the images 'snap in position' (at least in FireFox). The obvious solution for this is to have the containers show the images after resizing the container. (solution 2)

This may be worth a quick try. When inspecting the Fiddle, I noticed that #wrapper1 had a width of 400px and #wrapper2 had a width of 399px. I changed the width of #wrapper2 to 400px for consistency.
I added background-size:cover; to the button because the button image appears to be a different size than its container. Give this a try and see what you think.
If you need to keep #wrapper2 at 399px, then change the background position in the code below to background-position:top left; while using background-size:cover;.
Another option for your current code would be to make the background image the same size as its 12px by 12px container, use background-position:top left;, and remove the background color. When creating button backgrounds, its helpful if the background is the same size as its container.
Note: You could also use CSS styles to create the button look on the div, and not use an image.
Here's the JSFiddle
Here's the browser support table from Can I Use for background-size:cover.
#wrapper1 {width:400px;}
#wrapper2 {width:400px;}
#container {
width:12px;
height:12px;
background-repeat:no-repeat;
background-position:center center;
background-size:cover;
-webkit-background-size:cover;
-moz-background-size:cover;
-o-background-size:cover;
background-image:url(data:image/gif;base64,R0lGODlhCQAJALMAANLNve/s58a7rd7Vznuatf////f39wAAALXD1vfz7+fj3tbTxsa6pdbPxt7b0sa2pSH5BAAAAAAALAAAAAAJAAkAAAQoEJFJiSw4l6mxmUYYJgp4nKczJUngKsOkOMOyNMAECALDPAJLhYKIAAA7);
}

Related

Centering HTML table wider than body

When an HTML table is wider than the page body, it's always left aligned, no matter if you specified a centered alignment. I've a table containing CSS3 gradient buttons, whose size isn't easy to predict (buttons size depends on the font used by the browser). On some browsers this table grows wider than the page body, causing the table to become uncentered related to the page banner.
I've read questions like this: Center table, even if it is wider than parent container stating that the only way of centering tables in this scenario is with Javascript.
But I'd wish to find a solution without javascript. The page design is very simple (just the site logo centered on the header, and an array of big buttons below).
Do you have any suggestion for an easy and elegant solution for this, so that the buttons table is always centered in the page?
http://jsfiddle.net/JQ3qb/
I'm not sure but is, this what you want? You can do it with positioning and then play with left percentage to adjust table.
#test{
border: 1px black solid;
width: 800px;
position:relative;
left: -25%;
text-align:center;
}

CSS background starting below variable header

Question
I'd like the CSS background texture for my content area to begin immediately after a variable-height header. The texture has a natural height of 900px and is graduated to a flat color, so if it fits in the available space between content-start and body-end, the whole texture should be displayed. The texture shouldn't artificially expand the content area or cause unnecessary scroll, but scroll should still appear when content is longer than fits in the page.
JSFiddle
On request, here's a JSFiddle of my issue. Since there's really only one DOM element in the question, I think the fiddle doesn't clarify much. http://jsfiddle.net/AbEUe/5/
What doesn't work
#contentAndBackground {
padding-bottom: 900px;
margin-bottom: -900px;
background: url('my900pxHighImage.png') repeat-x;
}
The above ensures the whole image is shown, but the negative margin doesn't keep the unnecessary scrollbars away as I'd hoped.
#contentAndBackground {
min-height: 900px;
background: url('my900pxHighImage.png') repeat-x;
}
Same problem. The whole image is shown, but scrollbars are always showing.
I'd like to avoid using JavaScript that needs to handle screen resizing.
I think I did it: http://jsfiddle.net/AbEUe/7/
I have created 2 container divs, both have a height of 100%.
The first contains header and background, and has overflow:hidden so the background is stopped at the bottom.
The second contains header and content, and because of use of positioning this one is on top of the first container, and it can stretch to more than 100% (if the amount of text requires that).
You can see you have to render the header twice, but that won't matter because the first isnt visible.
Edit:
Solved the last problem (see comment) by also setting the background to the content div. See http://jsfiddle.net/AbEUe/8/
Your question is not very clear, but this prevents your kitties from being chopped up.
#content {background: url('http://placekitten.com/g/200/300') repeat-x; min-height:300px;}

3 vertical background images appear as one image with content in center image. Center image "cuts off" and does not match footer image

jsfiddle link: http://jsfiddle.net/djDWF/84/
The problem is, the inner container (text-padding) margin/width for the text/images is affecting the center background image. The repeated image that touches the footer does not extend to full height, and cuts off so the center and footer images do not match up (it is kind of hard to tell, but if you add or remove text in my jfiddle example you can see the center image change where it meets the footer.).
This is for a school project, and though I did not need to actually do this type of image background, I got this far so might as well continue. I don't want to use javaScript if possible because that is not part of the course yet.
I tried removing the text wrapper and styling each p tag individually but the same effect occurs.
I also tried mathematical combinations using line-height and margins. If I set the line-height to equal the right and bottom margins, and the left margin to equal the height of the footer then the effect works, but because my footer image is so large this is not a workable solution.
Mathematically I tried to keep the same ratios with the footer height but this did not work either (or else I did this wrong. I tried dividing each by the same amount.)
Is there any way to do this using only CSS and and not having to resort to tables?
So in short the problem is: You can see a line showing up at the footer separation because the repeated centre background isn't fully showing it's last repeat as the container isn't big enough.
The solution: If it doesn't need to be variable and you know how much content you will be putting in you can just set a height: Live example - http://jsfiddle.net/djDWF/85.
div#background-center{
background:url(http://i.imgur.com/gsNFa.png) repeat-y;
float:left;
width:700px;
height: 1604px; /* add this */
}
Obviously, pick whatever height is right to fit your final text.
With your current images there is no way to do this automatically without using JavaScript.

Is this a -webkit-box-reflect bug

While I developing a div image box with reflection -webkit-box-reflect, I found out that the reflection at bottom not mirroring exactly from the bottom of the image. It depends on how much size available for the reflection.
For better illustration of the problem:
http://jsfiddle.net/mochatony/4B26Q/14/
The 2 images have the different reflection, one from the middle and one from bottom of the image, which I expect reflection is from the bottom. The reflection is somehow depends on how much html height available, it the space allow for full shadow display, it will reflect the image at the bottom (you can adjust the slider of the html panel to adjust the size).
Is there a way to fix the reflection start from the bottom of the image regardless of space available?
Try the same code by removing width and height in box1 and box2 as follows:
#box1{
position:fixed;
margin-left:20%;
margin-top:0%;
-webkit-box-reflect: below;
}

How to make overflow: hidden really hide content?

Please, look at this example. I intend making horizontal layout with pure html/css, don't bother of old browsers. I made it with display: table technique. But displaying main text containers (light-yellow) became a problem. Each of this has overflow: hidden to prevent vertical scroll. Later, I intend adding some shadow effect at the bottom. Now, I want to make in, for example, 80% height with 10% margin top and bottom. But what I get is container with larger text stretching all parents container (light-green), so 80% of it became too much.
Is there any way to avoid it without javascript?
Maybe I can get text container any height, but with some margin at the bottom. I will appreciate any solution.
Do not use table layouts, table cell divs have a problem setting their width/height and thus will not be able to follow overflow rules.
update the following css properties in your layout.css, this will get you started:
#content{
display:block;
height:90%;
overflow:hidden;
vertical-align:top;
}
#content-inner{
display:block;
height:100%;
vertical-align:top;
}
.article{
display:inline-block;
}
It's still not clear what you want; maybe post a quick sketch?
Anyway, I'd want to avoid the horizontal scrollbar. To do that set #content {
width: 61%;} (based on the rest of the CSS). Currently, in layout.css, #content width is set to 305%.
RE:
#Brock Adam, I mean I want to make div.article-content 80% of screen, not 80% of parent container. I believe this can be achieved by forcing parent div#content be exactly 100% of screen, not more. But I don't know how.
div.article-content currently appears 5 times in the page. Setting it to 80% of the screen will give a page that's at least 400% wider than what the user can see.
Questions:
The first div is ID'd as "header", but it's floated left and only 39% wide. Is this a header (bar at top of of page) or a left, side-bar?
Are the articles supposed to be in 5 tiny columns, on the same row, or are they supposed to be one after another, scrolling down the page?
Again, statements and the semantics of the example page are unclear. Posting a quick sketch of the desired layout will help us help you.