Make a relatively positioned div square with CSS - html

I would like to know if there is a CSS only solution to make sure that a relatively positioned div would be exactly square under any circumstances; I have a script that would allow a user to upload an image which would apply it to the background image property.
The problem is that the system needs to support images of all sizes, so I can't just set a specific height and width.

Step 1
Simply give the div padding-bottom of 100% to create an intrinsic ratio, which means the div will always be square, no matter the width. Then use position: relative/absolute to position a child element that strechtes the whole container.
This is a common CSS only technique to embed videos at certain aspect ratios, but it's not limited to that specific content type.
I created a fiddle to see it in action. Please note: I used SuitCSS' flex embed component here, but you are in no way bound to using it.
http://jsfiddle.net/mlnmln/tfm6q/1/
HTML:
<div class="FlexEmbed FlexEmbed-ratio">
<div class="UserImage FlexEmbed-content"></div>
</div>
CSS:
/*
* FlexEmbed component from suit-css.
* #see: https://github.com/suitcss/components-flex-embed/blob/master/lib/flex-embed.css
* #see: http://suitcss.github.io/components-flex-embed/test/
* #see: http://alistapart.com/article/creating-intrinsic-ratios-for-video
*/
.FlexEmbed {
display: block;
overflow: hidden;
position: relative;
}
/**
* The aspect-ratio hack is applied to an empty element because it allows
* the component to respect `max-height`. Default aspect ratio is 1:1.
*/
.FlexEmbed-ratio {
display: block;
padding-bottom: 100%;
width: 100%;
}
/**
* Fit the content to the aspect ratio
*/
.FlexEmbed-content {
bottom: 0;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
Step 2
Find a method to resize image to fit/fill its container. I would suggest the following solutions.
Backend: Crop the image through an image manipulation library like GDlib or ImageMagick. That way users will only have to download the data they need.
CSS: Use background-size: cover if your don't care about legacy browser support and don't have access to server side image manipulation.
.UserImage {
background-size: cover;
background-image: url(http://placekitten.com/200/400);
}
3: JS: Position and crop the image container using DOM manipulation. This is basically the same Math as using a server-side image library, with the disadvantage that you place the load on the client (bandwidth and processing).
Hoping to help.

Related

Make aspect ratio of responsive iframe same as ratio of screen/window size

I'm trying to insert basic html (local file) into a parent html. From my previous question I concluded that jquery load might never work in prod so I attempted to use iframe as per Makesh Keshu's suggestion. It sort of does what I want, but now I'm running into some styling issues? Since the local file I'm trying to embed is just text essentially, I want it to just look like the parent html holds the text (aka responsive sizing and all) -- motivation for embedding the html and not just writing it in directly is mainly because the site owner wants to try to make the text entry not "steal-able" from just doing inspect and copying the text away.
My css right now uses an iframe wrapper class that does the usual that everyone else suggests:
.text-wrapper {
position: relative;
padding-bottom: 100%;
padding-top: 100%;
height: 0;
overflow: hidden;
}
.text-wrapper iframe {
position: absolute;
border: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
}
However, I suspect due to the aspect ratio from the padding attributes, it looks great when my screen is in split-screen view or on mobile, but when I resize the screen to full screen, there is a lot of white space under all the text to keep the container at roughly the half-screen-view aspect ratio. (Please correct me if this assumption is wrong -- I'm still a beginner with front-end.)
Basically, I want to try to make the aspect ratio of the iframe container the same as the ratio of the tab/window/screen -- which changes as window resizes and whatnot.
I looked through this question because it seems similar, but I'm neither sure I understand the idea behind the answer very well nor am I sure it really answers my question. That question I think is asking to size the iframe-container according to the content size without using a fixed aspect ratio, which would achieve the same thing, but I'm trying to see if I can just make the aspect ratio responsive based on the "screen"(window?) ratio.
This article ended up working really well for my specific purposes. I'm not sure I 100% understand the theory behind it yet, but it uses a pseudo-element. It seems to have solved my problem of having extraneous whitespace in the iframe container in full-screen, but I'm not sure if it solves the general issue (for people who want to try the method out).
The css code I ended up using (for the container, css for iframe remains the same):
.aspect-ratio-box {
background: white;
}
.text-wrapper::before {
content: "";
width: 1px;
margin-left: -1px;
float: left;
height: 0;
padding-top: 52.46%;
}
.text-wrapper::after {
content: "";
display: table;
clear: both;
}

Define table width & height in CSS, so it has a specific width/height ratio when printed

I have a table on my webpage, that uses a specific print CSS, that removes all the web site elements so that it can be printed on posters.
What I do is:
Visit the page with Google Chrome,
Click: File -> Print -> "Print using system dialog...",
Click PDF -> "Save as PostScript", and
Process with Adobe Distiller (150 dpi & 18” x 24”).
Since I want my table to fill the 18"x24" (18/24 = 3/4) poster nicely, how can I make sure that its width/height aspect ration is 3/4, without putting in specific dimensions that would come to bite me in print?
For now, the only solution that came to my head is the one where you'd have to wrap the table with two additional divs.
Here's the fiddle
As we speak, I'm trying to improve the solution to get rid of the divs.
At the moment I'm using one div as a wrapper with width set to 100%, then inside of it there is another div (innerWrapper) which is positioned absolutely and spread to the wrapper's dimensions. To set the div's height I used a simple trick - added a pseudo :after element to the wrapper which has padding-bottom set to 133%. Padding percentage values are inherited from parent's width (yes!). In case of somebody asking - we can't ommit the innerWrapper div and set its style directly to table becuase top, right, bottom, left method won't work for it (neither width and height set to 100%). Divs are block elements, tables have display: table.
Whole code looks like this:
HTML:
<div id="wrapper">
<div id="innerWrapper">
<table></table>
</div>
</div>
CSS:
#wrapper {
width:100%;
position: relative;
}
#wrapper:after {
content: "";
display: block;
padding-bottom: 133%;
}
#innerWrapper {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
table {
width: 100%;
height: 100%;
}

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.

Alternative for background-size:cover in IE7+

I have a background image on the body of my web page. I have used background-size:cover so that the image stretches across the body whilst maintaining the aspect ratio of the image. I would like this to be the same for IE7 + IE8.
I have looked around and seen the following code:
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='AutumnWinter_4.jpg',
sizingMethod='scale');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='AutumnWinter_4.jpg',
sizingMethod='scale')";
But this doesn't preserve the aspect ratio, which is really bad for the website we are aiming at.
Is there any way to do this? Without hitting up jQuery?
What's the reason of not using jQuery? You could load it in conditional comments for IE<8 only, so that for every other modern browser jQuery is not loaded.
Also consider that IE7 has a very low market share (2,52%, April 2012) so it can be acceptable to load ~ 25kb extra for that specific browser if this feature is so important for your site/application.
So, I've found this plugin for jQuery: https://github.com/louisremi/jquery.backgroundSize.js
A jQuery cssHook adding support for "cover" and "contain" to IE6-7-8, in 1.5K
See Github project page for more info.
backgroundSize.js will not actually stretch the bg image in IE7, it seems to just center it at the original size. See their demo and click on 'Check what IE6-7-8 users would normally see.'
#danRhul
I have read that backstretch will work in IE7+
Good luck!
You could just fake a background image with an actual image. It's a bit more HTML editing and certainly not ideal, but since when has handling IE ever been ideal?
<body>
<img id="mainBG" src="mainBG.jpg" />
<div id="content">
[ ... ]
Then style it accordingly
body{
position:relative;
}
#mainBG{
width:100%
position:absolute;
top:0px;
left:0px;
}
Should be cross-browser if I'm not mistaken.
I've used the following (http://css-tricks.com/perfect-full-page-background-image/) and it works well in ie7.
HTML:
<body>
<img class="bg" src="filename">
</body>
CSS:
.bg {
/* Set rules to fill background */
min-height: 100%;
min-width: 1024px;
/* Set up proportionate scaling */
width: 100%;
height: auto;
/* Set up positioning */
position: fixed;
top: 0;
left: 0;
}
#media screen and (max-width: 1024px) { /* Specific to this particular image */
img.bg {
left: 50%;
margin-left: -512px; /* 50% */
}
}
I know this is now an old question, but I thought I'd share a solution I came up with for anyone else who finds this question on google, like I did.
I was trying to get an image to cover a site's background and came across this question, however none of the solutions worked for me. I came up with this instead:
HTML: move the background image to an <img />, make it the first thing in your <body>.
<html>
<body>
<img class="background" src="kitty.jpg" />
<div class="content">
...
CSS: make the background appear under the content, set it's min-width/height to 100%.
html {
height: 100%
}
body .background {
position: absolute;
z-index: -1;
min-height: 100%;
min-width: 100%;
}
It's the min-height and min-width here that does the magic. Do not give the image a width and height in the HTML or CSS, or the aspect ratio will change.
The above will work for IE7 and IE8. If you would like to support IE6, you could set a centered image fallback like this:
CSS: If IE6, don't display the image, use a background image instead.
body {
_background: url("kitty.jpg") 50% top no-repeat;
}
body .background {
_display: none;
}
(N.B. If you don't like the underscore hack to target IE6, you could use conditionals instead – that's what the HTML5 Boilerplate does.)
After much trial and error, the best solution was guessing it!
The following worked for me.
body {
background-size:100%;
}
You have two options to achieve this with just CSS:
Use Object-fit: cover. The only problem with this is that it will not work in all browsers
If you want cross browser support, you can follow primitive CSS approach:
Position the image inside the container with absolute and then place it right at the centre using the combination:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
Note:
Since transform ONLY works from IE9, you can make use of filters. Here is an answer for this.
Once it is in the centre, you can do,
// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;
// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;
This makes the image get the effect of Object-fit:cover.
Here is a demonstration of the above logic.
https://jsfiddle.net/furqan_694/s3xLe1gp/
Unfortunately, most solutions to this kind of problem either depend on css3 or ignore the native functionality of "cover" that preserves the original aspect ratio of the image. https://github.com/louisremi/background-size-polyfill is supposed to preserve ratio, but I could never get it to work completely when stretching the browser in certain ways (operator error, I'm sure :-) ). To solve this problem, I wrote a jquery script that I've tested on safari, chrome, ff and ie8+. You'll notice that you will have to use an img positioned absolutely instead of css background-image. Just add the bgImg as an id in the tag in html.
CSS:
.container { height: auto; overflow:hidden; position:relative;}
.container #bgImg { position:absolute; z-index:-1;}
You're image selector will have to be positioned absolutely to get it to sit behind the content. That means that you're parent container has to have position: relative and then overflow: hidden so that whatever overflows from the image (since you're maintaining ratio, some pieces of it inevitable will) is hidden. Be aware also that certain display tags in the parent container will break the hiding of the overflow.
JQUERY:
$(window).load(function () {
// only do this once and pass as function parameters, because chrome
// and safari have trouble not only with document.ready but window.resize
var img = new Image();
img.src = $("#bgImg").attr('src');
var $width_orig = img.width;
var $height_orig = img.height;
resizeBGImage($width_orig, $height_orig);
$(window).resize(function () {
resizeBGImage($width_orig, $height_orig);
});
});
function resizeBGImage($width_img_orig, $height_img_orig) {
// get dimensions of container
var $width_container = $('.container').outerWidth();
var $height_container = $('.container').outerHeight();
// calculate original aspect ratio and ratio of the container
var $imageratio = $width_img_orig / $height_img_orig;
var $containerratio = $width_container / $height_container;
var $wdiff = $width_container - $width_img_orig;
var $hdiff = $height_container - $height_img_orig;
// original size, so just set to original
if (($wdiff == 0) && ($hdiff == 0)) {
$("#bgImg").css('width', $width_img_orig);
$("#bgImg").css('height', $height_img_orig);
}
// if container is smaller along both dimensions than the original image,
// set image to container size
else if (($wdiff < 0) && ($hdiff < 0)) {
$("#bgImg").css('width', $width_img_orig);
$("#bgImg").css('height', $height_img_orig+1); // adding one because chrome can't do math
}
// if container is wider than long relatiave to original image aspect ratio
// set width to container width and calculate height
else if ($containerratio > $imageratio) {
$("#bgImg").css('width', $width_container);
// calculate height using orig aspect ratio and assign to image height
$("#bgImg").css('height', (($width_container * $height_img_orig) / $width_img_orig) + 1); // adding one because chrome can't do math
}
// else container is taller than long relatiave to original image aspect ratio
// set height to container height and calculate width
else {
// set the image height to container height
$("#bgImg").css('height', $height_container + 1); // adding one because chrome can't do math
// calculate width using orig aspect ratio and assign to image width
$("#bgImg").css('width', (($height_container * $width_img_orig) / $height_img_orig));
}
$("#bgImg").css('left', (($width_container - $("#bgImg").width()) / 2).toString() + 'px');
};
Note the use of $(window).load() instead of $(document).ready(). Chrome and safari seem to have issues with the latter since in those browsers, the background image may not be fully loaded when the DOM is. Using $(window).load() ensures all window elements are in place before the script runs.
Sounds like you need a 'shim' or 'polyfill' like Modernizer:
http://modernizr.com/docs/#html5inie

Background image center and resize

I'm working on a site for a client in which there's a background image that will be centered on the page with text, links, etc. overlayed.
I currently have the image resized as follows:
img.bg
{
height:100%;
position:absolute;
}
This fits the image to the height of the browser, but aligns it to the left. I need it to be centered.
Since I need it to be conditionally responsive to browser-height variations, the usual centering tricks aren't working.
Thanks!
Try removing "position:absolute" and adding margin: 0 auto. For example:
img.bg
{
height:100%;
margin: 0 auto;
}
or may be just place it inside a table <table align="center"> <tr><td>"image goes here"</td></tr> it's easier to manage cause you can add more items to the webpage in future without difficulty, add borders, change colours of tables, etc.
I can think of a couple ways to go about it (untested, so you'll probably have to tweak):
img.bg {
position: absolute;
/* Top and/or bottom for stretching it vertically as needed. Setting both will likely make it the size of the whole body, so beware. Remove bottom to keep it from doing that if necessary. */
top: 0;
bottom: 0;
/* Left and/or right for sizing/positioning */
left: 25%; /* Percentage position will make it adjust to browser window size, exact percent may need to be tweaked to get right and will depend on the image's size. */
}
img.bg {
display: block;
height: 100%;
width: 500px; /* Whatever your desired width is. */
margin: 0 auto; /* This should work as long as width is set. */
}
Depending on your exact design, either of these should work and be responsive to the size of the browser window. The second one is probably the most flexible and easiest to implement, since you don't have to fiddle with positioning.
The answer depends on exactly what you are after.
If you want an image displayed in the background of the website (which I think you are saying) then I am not sure what method you are using, but if you do away with your img.bg{} in your html and css, and just put the following into your CSS you will get what you want...
body{
background-image:url('background.gif'); // substitute background.gif for the correct file path
background-repeat:no-repeat;
background-attachment:fixed;
background-position:center;
background-size:auto 100%;
}