Inscribe and center an image within a frame - javascript

Given a div of arbitrary aspect ratio, what's the best way to place and style an image (also with an arbitrary aspect ratio) inside such that:
It is both inscribed and centered
Its dimensions and position are set using relative values so that the image will remain inscribed and centered automatically when the frame is uniformly scaled (javascript should only be required when the image is initially inserted, or if the frame's aspect ratio changes)
Extra markup is minimized
Here's the result we want:
Here's a fiddle template, which is just:
Markup
Should pillarbox
<div class="frame">
<img src="http://www.placekitten.com/200/300" />
</div>
Should letterbox
<div class="frame">
<img src="http://www.placekitten.com/300/200" />
</div>
CSS
.frame {
width: 200px;
height: 200px;
border: 2px solid black;
margin: 10px 0px 100px 0;
}

You can try something like this: updated fiddle
.frame {
width: 200px;
height: 200px;
border: 2px solid black;
margin: 10px 0px 100px 0;
position: relative; /* added */
}
img {
max-height: 100%;
max-width: 100%;
position: absolute;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
}

By combining Adrift's css
.frame {
width: 400px;
height: 400px;
border: 2px solid black;
margin: 10px 0px 100px 0;
position: relative; /* added */
}
img {
max-height: 100%;
max-width: 100%;
position: absolute;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
}
with javascript
var inscribe = function(img, frame) {
var imgRatio = img.width / img.height;
var frameRatio = frame.offsetWidth / frame.offsetHeight;
if (imgRatio > frameRatio) { // image is wider than frame; letterbox
img.style.width = '100%';
img.style.height = 'auto';
} else { // image is taller than frame; pillarbox
img.style.width = 'auto';
img.style.height = '100%';
}
}
all requirements can be satisfied.
http://jsfiddle.net/PBPkh/4/

Well you can achieve that with background-images too, if you can get rid of the <img /> elements.
There is a css property on background-size called contain, that does the job:
.background{
background-size: contain;
}
And if you wish to center the image just add this:
background-position: center center;

Related

Changing between 2 background colours on mouse Y + adapting <p> to that new colour

I found a piece of code that almost does what I want except I want it to be horizontal / based on mouse Y instead of X. Now I understand that in the js X will be changed to Y, but I struggle with rotating the divs.
Also, if I want to put some text over it, how would I do so that the background change affects the text colour (so if the text is black and half of the background is black, to make sure once when the black background overlays the text, text colour changes to another or gets inverted for example?
Also also, I tried to figure out in js which part dictates the responsiveness of the mouse movement, i.e., how would you do so that the colour shifting is not lagging after the mouse but I couldn't figure out?
https://codepen.io/erutuf/pen/NJLwqV
haml
#banner-wrapper.banner-wrapper
.banner.design
.banner-content
.banner.dev
.banner-content
scss
body {
margin: 0;
padding: 0;
.banner-wrapper {
position: relative;
width: 100%;
height: 400px;
overflow: hidden; background:red;
}
.banner {
position: absolute;
overflow: hidden;
&.dev {
margin-left: -500px;
width: calc(50vw + 500px);
.banner-content {
margin-left: 500px; background:black;
}
}
.banner-content {
height: 400px;
}
img {
width: 100vw;
}
}
}
js
document.addEventListener('DOMContentLoaded', function(){
let banner = document.getElementById('banner-wrapper');
let devLayer = banner.querySelector('.dev');
let delta = 0;
banner.addEventListener('mousemove', function(e){
delta = (e.clientX - window.innerWidth / 2) * 0.5;
devLayer.style.width = e.clientX + 500 + delta + 'px';
});
})
you can play with JS + CSS. The following code can be your starting point :).
btw i'm adapting code from your link https://codepen.io/erutuf/pen/NJLwqV
document.addEventListener("DOMContentLoaded", function(){
let banner = document.getElementById("banner-wrapper");
let devLayer = banner.querySelector(".dev");
let delta = 0;
// play with div's height
banner.addEventListener("mousemove", function(e){
delta = (e.clientY - window.innerHeight / 2) * 0.5;
devLayer.style.height = e.clientY + delta + "px";
});
})
<div class="banner-wrapper" id="banner-wrapper">
<div class="banner design">
<div class="banner-content">BANNER TEXT</div>
</div>
<div class="banner dev">
<div class="banner-content"></div>
</div>
</div>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
body .banner-wrapper {
position: relative;
width: 100%;
height: 200px;
overflow: hidden;
background: red;
}
body .banner {
position: absolute;
overflow: hidden;
}
body .banner.dev {
width: 100%;
/* play with responsiveness here. note that 0.1 is more responsive than 0.5. more info : https://www.w3schools.com/css/css3_transitions.asp */
-webkit-transition: height 0.2s linear;
transition: height 0.2s ease;
}
body .banner.dev .banner-content {
background: black;
}
body .banner .banner-content {
height: 400px;
}
body .banner img {
width: 100%;
}
.banner.design {
margin-top: -25px;
height: 50px;
top: 50%;
font-size: 50px;
/* set color & mix-blend-mode for text color vs background color effect. more info : https://css-tricks.com/methods-contrasting-text-backgrounds/ */
mix-blend-mode: difference;
color: #fff;
z-index: 1;
margin-left: -175px;
left: 50%;
width: 350px;
}
</style>

Create an image out of an svg + divs with bg-image

I want to convert some HTML (svg + divs with bg images) to an actual image, and save it to a directory using JS + PHP.
This is an example of the HTML:
https://jsfiddle.net/9k7u32s4/7/
HTML
<img src="http://svgur.com/i/5x3.svg" alt="">
<div>
<img src="http://svgur.com/i/5wM.svg" alt="">
<div class="d1" style="background-image: url(https://picsum.photos/400/250/?image=114)"></div>
<div class="d2" style="background-image: url(https://picsum.photos/400/250/?image=115)"></div>
<div class="d3" style="background-image: url(https://picsum.photos/400/250/?image=116)"></div>
</div>
CSS
html,body{
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
body > img{
height: 24rem;
position: absolute;
display: block;
left: 0;
right: 0;
bottom: 0;
margin: auto;
top: 0;
z-index: 20;
}
body > div > img{
height: 24rem;
position: relative;
display: block;
left: 0;
right: 0;
opacity: 0;
bottom: 0;
margin: auto;
top: 0;
}
body > div{
position: relative;
z-index: 15;
}
body > div > div{
background-size: cover;
background-repeat: no-repeat;
background-position: center;
width: 100%;
height: calc(100% / 3);
position: absolute;
left: 0;
}
body > div > .d1{
top: 0;
}
body > div > .d2{
top: calc(100% / 3);
}
body > div > .d3{
top: calc((100% / 3) * 2);
}
This is how it looks:
And this is how it should look after converting it to an image:
What is the simplest way to achieve this? Thanks in advance!
The most accurate way would be to build up your image in a <canvas> element. You would do this by using ctx.drawImage to add dom elements to the canvas and position them (svg's and your background images).
That way you could use canvas.toDataURL("image/png") and save it as an image once it was made. That's the JS part. Then once you have the file, save it to a database with PHP.
There are libraries out there like https://html2canvas.hertzen.com/ that you could try, they take a dom object and make them into a png, however they're not always the most accurate, as they have to accommodate for all kinds of css selectors etc.

Resizing image to perfectly fit a div with variable dimensions

I need to scale an image inside a div properly, so that the image keeps its proportions and so that either the width is equal to 100% or the height is equal to 100%.
So basically that the image takes up as much space as possible in the div whilst maintaining aspect ratio. And lets keep in mind that the div can change width and height.
So I have the intuition for this, but I don't have the code ...
The idea would be to get the ratio (height/width) of the div with
JavaScript/jQuery. => ratio A Then get ratio (height/width) of the image. => ratio B
Note: If ratio > 1, then we have a portrait image or div.
And if ratio < 1, then we have a landscape image or div.
If ratio A < ratio B, then we want height of image to be set at 100%;
If ratio A > ratio B, then we want width of image to be set at 100%;
So if we have a responsive div, width or height = 100% will change dynamically.
Is this possible?
Here are 2(css) solutions :
http://codepen.io/cryptcslaughtr/pen/LNoMBY
.container {
width: 100px;
height: 200px;
border: 1px solid #333;
background: url("https://3.bp.blogspot.com/-W__wiaHUjwI/Vt3Grd8df0I/AAAAAAAAA78/7xqUNj8ujtY/s1600/image02.png") no-repeat left top / contain;
}
<div class="container"></div>
http://codepen.io/cryptcslaughtr/pen/qZGLvE
.container {
width: 250px;
height: 130px;
border: 1px solid #333;
}
.container img {
max-width: 100%;
max-height: 100%;
}
<div class="container">
<img src="https://3.bp.blogspot.com/-W__wiaHUjwI/Vt3Grd8df0I/AAAAAAAAA78/7xqUNj8ujtY/s1600/image02.png" alt="Put your image" />
</div>
You can simply set parent div to position relative, and overflow hidden. And then do this:
.bg-img {
bottom: -1000px;
left: -1000px;
margin: auto;
min-height: 100%;
min-width: 100%;
position: absolute;
right: -1000px;
top: -1000px;
}
This will insure no matter whats the size of the container it will always cover it 100%. This will also contain image proportions.
If you need img tag for SEO/alt/ARIA/whatever, here is modified Cryptc_Slaughtr's solutions combined into one:
.container {
width: 250px;
height: 200px;
border: 1px solid #333;
background: url("https://3.bp.blogspot.com/-W__wiaHUjwI/Vt3Grd8df0I/AAAAAAAAA78/7xqUNj8ujtY/s1600/image02.png") no-repeat left top / contain;
}
.container img {
width:100%;
height: 100%;
opacity:0;
}
<div class="container"><img src="https://3.bp.blogspot.com/-W__wiaHUjwI/Vt3Grd8df0I/AAAAAAAAA78/7xqUNj8ujtY/s1600/image02.png" alt="Put your image" title="Put your image" /></div>

Jquery $(window).height() gives wrong value when setting height for document element

So my problem is when i get $(window).height() of an empty document it gives the correct value, but when i set a height for the div (.main-header) the $(window).height() gives it's value plus value close to the div height ,
this picture when i set a height 0 for the .main-header div
and this when i set 700px height for .main-header
i have tried $(window).load() and $(document).ready() and both gave same value https://jsfiddle.net/nev5onff/
$(window).load(function () {
var header = $('.main-header'),
windowH = $(window).height();
$('.test').text( windowH);
});
.main-header {
width: 100%;
height: 700px;
box-shadow: 0 1px 4px #888;
position: relative;
overflow: hidden;
}
.test {
position: fixed;
top: 0;
left: 0;
width: 100px;
float: left;
height: 100px;
background-color: #eee;
color: #000;
padding: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div class="test"></div>
<header class="main-header"></header>
I'm not sure if I understand your question, but I'll try and answer the best I can.
Weave: Pure JS
http://kodeweave.sourceforge.net/editor/#f722c9d64b3e290ec7cc9b4c1a6d19b8
So if you're trying to grab the height of your window/document you can use... (I'm using vanilla/plain js)
var test = document.querySelector('.test');
test.textContent = window.innerHeight;
However if you were grabbing the height of an element, if it has padding that sometimes can add to the elements height depending on how it's styled regardless if it's height is 0 or auto.
In some cases you may want to use clientHeight over innerHeight source
var test = document.querySelector('.test'),
mainHeader = document.querySelector('.main-header');
test.innerHTML = test.clientHeight
Here's a simple fiddle demonstrating this process.
var test = document.querySelector('.test'),
mainHeader = document.querySelector('.main-header');
test.innerHTML = test.clientHeight
.main-header {
width: 100%;
height: 700px;
box-shadow: 0 1px 4px #888;
position: relative;
overflow: hidden;
}
.test {
position: fixed;
top: 0;
left: 0;
width: 100px;
float: left;
height: 100px;
background-color: #eee;
color: #000;
padding: 20px;
}
<div class="test"></div>
<header class="main-header"></header>

Best way to center div in responsive div

I've been trying for several hours to both vertically and horizontally center a div with no specific width or height in a parent div that has a max-width and max-height but will be responsive. I've looked at both CSS and JS/jQuery options with nothing working properly.
As you can see, it's a thumbnail preview for a video. When in a normal state, it just shows the thumbnail with a play icon above it. In a hover state, it changes the play button to an orange one, displays the title, and has a black transparent overlay above the thumbnail.
Now, this would be easy to do with CSS if the site wasn't responsive. But, as the browser width decreases, the thumbnail sizes decrease.
Here's the HTML I'm using:
<article class="movie"><a href="#">
<div class="movie-overlay">
<div class="movie-play"></div>
<h2 class="movie-title">Title Goes Here</h2>
</div> <!-- end .movie-overlay -->
<div class="movie-thumb"><img src="thumbs/thumb.jpg"/></div>
</a></article> <!-- end #post- -->
And here's my CSS:
.movie-archive .movie {
width: 50%;
height: auto;
max-width: 480px;
position: relative;
overflow: hidden;
float: left;
}
.movie-archive .movie .movie-overlay {
width: 100%;
height: 100%;
position: absolute;
text-align: center;
}
.movie-archive .movie:hover .movie-overlay {background: rgba(0, 0, 0, 0.6);}
.movie-archive .movie .movie-play {
background: url("images/play-icon#2x.png") no-repeat center 0;
background-size: 94px 190px;
width: 100%;
height: 95px;
}
.movie-archive .movie:hover .movie-play {background-position-y: -95px;}
.movie-archive .movie .movie-title {
font-size: 17px;
letter-spacing: -0.01em;
font-weight: 700;
color: #ffffff;
display: none;
padding: 10px 50px 0;
}
.movie-archive #latest-top.movie:hover .movie-title, .movie:hover .movie-title {display: block;}
.movie-archive .movie .movie-thumb img {
width: 100%;
height: 100%;
display: block;
}
I've tried various things from adding another div and using the display: table trick to adding padding as a percentage, and using JS. Nothing seems to work. Does anyone have any suggestions? I would really appreciate it. Thanks!
Not that it really matters, but I am using WordPress for this site.
The container and the elemented you want centered should have properties like this:
.movie-archive .movie {
width: 50%;
height: auto;
max-width: 480px;
position: relative;
overflow: hidden;
float: left;
}
.movie-archive .movie .movie-overlay {
width: 100%;
height: 100%;
left: 50%;
margin-left: -50%; //half of width
top: 50%;
margin-top: -50%; //half of height
position: absolute;
text-align: center; //only if you want the text to be centered
}
Source: http://designshack.net/articles/css/how-to-center-anything-with-css/
try this:
$(document).ready(function() {w = $(window).width();
h = $(window).height();
jQuery.each($('.centerony'), function(i, val) {
lung = $(val).css('height');
a = (h * 0.5) - ((parseInt(lung)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('top', a + 'px')
});
jQuery.each($('.centeronx'), function(i, val) {
larg = $(val).css('width');
a = (w * 0.5) - ((parseInt(larg)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('left', a + 'px')
});
$(window).resize(function() {
k = $(window).width();
z = $(window).height();
jQuery.each($('.centeronx'), function(i, val) {
larg = $(val).css('width');
a = (k * 0.5) - ((parseInt(larg)) * 0.5);
$(val).css('left', a + 'px')
})
jQuery.each($('.centerony'), function(i, val) {
lung = $(val).css('height');
a = (z * 0.5) - ((parseInt(lung)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('top', a + 'px')
});
});
});
Add to the element you want to center class 'centerony' and class 'centeronx', and set parent's div (the one which has max-width and max-height with position:relative. It should work.
<div id="outdiv" class="outside" style="position:relative">
<div class="in_div centerony centeronx">I am centered!</div>
</div>
You have to use include jQuery to use it. :)
PAY ATTENTION -------
the code i wrote works according to window's size, and not parent's div size.
If you want to adapt to your case, change the values of vars w,h,k,z, making their value in relation with parent's div size instead of window size. for example w = $('#outdiv').width() instead of w = $(window).width();

Categories