Crop image into square and then to circle using pure CSS? - html

I'm trying to make a circle out of images with different sizes and different shapes (some rectangle, some sqaure, some portrait, some landscape).
When I'm using: clip-path: circle(50% at 50% 50%); or border-radius: 50%;, it turns the image into a perfect circle, only if the image is square:
Is there a way to crop an image into a square and then use one of these methods to make it a perfect circle:
Using pure CSS withou using background-image (most images are given the background image from server side),
Keeping a 50% ratio - without losing aspect ratio - (both if border-radius or clip-path)(Images size may vary).
Here's a code snippet to show a square image and a rectangle image:
.clipped {
clip-path: circle(50% at 50% 50%);
}
Square<br>
<img src='http://i.imgur.com/d5byNNR.jpg' width="100" class='clipped' /><br><br>
Rectangle<br>
<img src='http://i.imgur.com/22W12EQ.jpg' width="100" class='clipped' />

You can use circle() but without the parameters:
.clipped {
clip-path: circle();
}
It appears to use the smaller side of your image as the circle's circumference.
Working sample here.
It works on Chrome and FireFox. IE and Edge still does not support clip-path

That's an another way to do it using pure CSS:
HTML
<div class="circular--portrait">
<img src='http://i.imgur.com/22W12EQ.jpg'/>
</div>
CSS
.circular--portrait {
position: relative;
overflow: hidden;
width: 100px;
height: 100px;
border-radius: 50%;
}
.circular--portrait img {
width: 100%;
height: auto;
margin-top: -30px;
}
Code Snippet (with portrait and landscape examples)

Alright, took me a moment but this is what I came up with:
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox, xOffSet, yOffSet) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
//result.targetleft = Math.floor((targetwidth - result.width) / 2);
//result.targettop = Math.floor((targetheight - result.height) / 2);
result.targetleft = Math.floor((targetwidth - result.width) / 2 - xOffSet);
result.targettop = Math.floor((targetheight - result.height) / 2 - yOffSet);
return result;
}
function OnImageLoad(evt, xOffSet = 0, yOffSet = 0) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).width();
var h = $(img).height();
var tw = $(img).parent().width();
var th = $(img).parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, false, xOffSet, yOffSet);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
.result {
width: 250px;
height: 250px;
border: thick solid #666666;
overflow: hidden;
position: relative;
border-radius: 50%;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
No offset:
<div class='result'>
<img src="http://i.imgur.com/22W12EQ.jpg" style="position: absolute;" onload="OnImageLoad(event, 0, 0);"/>
</div>
Y offset:
<div class='result'>
<img src="http://i.imgur.com/22W12EQ.jpg" style="position: absolute;" onload="OnImageLoad(event, 0, 30);"/>
</div>
I took most of the work from this resource: https://selbie.wordpress.com/2011/01/23/scale-crop-and-center-an-image-with-correct-aspect-ratio-in-html-and-javascript/ and I've adepted it to allow the use of Offsets so you can crop any image at the position you want.
How it works
You create a div of any size you want. It can be square, but if you want an egg-like result, that works as well (lol). Then insert the image of any unknown size inside it.
Change onload="OnImageLoad(event, 0, 30); with the offsets you want. Positive offsets for moving the image left or down, negative for up or right.
Note: I did use jQuery for this.

Related

Fill div with img in React

I'm trying to fill a div (black area in following screen) with an img.
But the scale of image should not change.
And when the size of the div changes according to the size of the browser, the image should be displayed by adjusting the width or adjusting the height accordingly.
The image changes dynamically, so I never know if it will be tall or long.
for example
Finally, the target is to make the image show as large as possible without changing the scale of the image.
Below is the code I developed.
<div className="asset__item">
<a className="asset__img">
<img
alt="item image"
src="/img/1.jpg"
/>
</a>
</div>
CSS
.asset__item {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
position: relative;
padding: 20px 20px 20px 20px;
width: 100%;
border-radius: 16px;
margin-top: 20px;
background: #202020;
}
.asset__item img {
width: auto;
max-width: 100%;
}
Please let me know how to fix it.
I try not to modify the styles of asset__item as much as possible.
But it's ok to add a div there instead.
You can try using object-fit :
`
img{
width: auto;
max-width: 100%;
object-fit:cover;
}
`
I could not find a way to do it using only CSS. So I directly assigned width and height to my image using JavaScript. We should handle 4 different situations:
Album picture and album screen
Album picture and portrait screen
Portrait picture and album screen
Portrait picture and portrait screen
My imgObj contains initial width and height of the image (I got them using react-image-size).
And here is the code:
const imageObj = useSelector((state) => state.imageHandling.imageObj);
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const handleImageSize = () => {
if (imageObj) {
let w = 0;
let h = 0;
const ratio = imageObj.width / imageObj.height;
const theSameTypes = () => {
w = window.innerWidth;
h = window.innerWidth / ratio;
if (h > window.innerHeight) {
h = window.innerHeight;
w = h * ratio;
}
};
if (imageObj.width > imageObj.height) {
if (window.innerWidth > window.innerHeight) {
theSameTypes(); //album picture and album screen
} else {
w = window.innerWidth; //album picture and portrait screen
h = w / ratio;
}
} else {
if (window.innerWidth > window.innerHeight) {
h = window.innerHeight; // portrait picture and album screen
w = h * ratio;
} else {
theSameTypes(); // portrait picture and portrait screen
}
}
setWidth(w);
setHeight(h);
}
};
useEffect(() => {
window.addEventListener("resize", handleImageSize);
return () => {
window.removeEventListener("resize", handleImageSize);
};
}, []);
useEffect(handleImageSize, [imageObj]);

Different sizes Images in a 100%-width-row

i am trying to put several images (five) next to each other in one row. The row should have the width of a 100%. It is important that the images all have the same height e.g.! Is there a way to manage this? I tried several code, e.g. a masonry, but it does not help me with the height of the images.
Thank you
(I am using Bootstrap if that's any help.)
Edited, new answer.
The code below should do the job.
Note that I have inserted comments between all the img tags in the html, this is to make sure that there is no spacing between the images and is therefore important for the code to work!
Also note that if you change the class of the div which contains the images, you will have to change the query selector in the javascript to match this.
Final note: the script is very laggy here in the code snippet. I tried it as an actual webpage and it was not laggy at all, so maybe try that too!
var repeat = true;
window.addEventListener("load", resizeImages);
window.addEventListener("resize", resizeImages);
function resizeImages() {
var i;
var images = document.querySelectorAll("div.row img");
var heights = [];
var widths = [];
for (i = 0; i < images.length; i++) {
heights.push(images[i].offsetHeight);
widths.push(images[i].offsetWidth);
}
var numerator = document.body.clientWidth;
for (i = 0; i < heights.length; i++) {
numerator *= heights[i];
}
var denominator = 0;
for (i = 0; i < widths.length; i++) {
var thisItem = widths[i];
for (i2 = 0; i2 < heights.length; i2++) {
if (i != i2) {
thisItem *= heights[i2];
}
}
denominator += thisItem;
}
var height = numerator / denominator;
for (i = 0; i < images.length; i++) {
images[i].height = height;
}
if (repeat) {
repeat = false;
setTimeout(function() {
resizeImages();
}, 300)
}
}
div.row {
white-space: nowrap;
}
<html>
<head>
<title></title>
</head>
<body>
<div class="row">
<img src="https://media.wired.com/photos/5926db217034dc5f91becd6b/master/w_1904,c_limit/so-logo-s.jpg" alt=""><!--
--><img style="padding-left:5px;" src="https://jessehouwing.net/content/images/size/w600/2018/07/stackoverflow-1.png" alt=""><!--
--><img src="http://www.andysowards.com/blog/assets/8-Best-Websites-That-Will-Hone-Your-Programming-Skills-7-1024x538.png" alt="">
</div>
</body>
</html>
I used CSS Grid for your implementation. .row is 100% width and each image can have its own custom scaling if need be.
Be aware, images are hard make constant because each image will come with its own ratio and size.
You can use background-size to set image property to your liking.
The background-size CSS property sets the size of the element's background image. The image can be left to its natural size, stretched, or constrained to fit the available space.
Hope the example below helps.
Reference background-size: https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
Reference CSS Grid: https://css-tricks.com/snippets/css/complete-guide-grid/
img {
height: 130px;
width: 100%;
}
.row{
width: 100%;
display: grid;
grid-template-rows: auto;
grid-template-columns: repeat(5, 1fr);
/* If each individual picture column need modification*/
/* grid-template-columns: auto 1fr 200px 15px 10%; */
}
<div class="row">
<img src="https://loremflickr.com/cache/resized/8447_7961096220_79eb4fb07c_c_640_360_nofilter.jpg" alt="">
<img src="https://loremflickr.com/cache/resized/65535_40670884373_757596f5d1_b_640_360_nofilter.jpg" alt="">
<img src="https://loremflickr.com/cache/resized/65535_47957578362_73f1562d77_z_640_360_nofilter.jpg" alt="">
<img src="https://loremflickr.com/cache/resized/65535_46970967485_3456a6be5f_z_640_360_nofilter.jpg" alt="">
<img src="https://loremflickr.com/cache/resized/2544_3722368834_5584ab3bc1_z_640_360_nofilter.jpg" alt="">
</div>

HTML/CSS - Automatically set height width from background image?

Longshot... I don't think this is possible but I've been shocked before!
I anchor tags, all of which have background images, all 300px wide but their heights all vary. Is there anyway to set these without actually having to type out the height? Sort of setting it to the bg url's dimensions?
Thanks!
I don't think people understand - My fault for rushing the question.
Here's code as an example:
#ex-1 {width: 300px; height: 410px; background: url('/image-1.jpg');}
#ex-2 {width: 300px; height: 420px; background: url('/image-2.jpg');}
#ex-3 {width: 300px; height: 430px; background: url('/image-3.jpg');}
#ex-4 {width: 300px; height: 440px; background: url('/image-3.jpg');}
I'd like to NOT set the height, and it set automatically using CSS only. I don't want to use image tags.
I wasn't sure if this was possible, I assume not.
Thanks
A simple way of doing this is to add an image like this and then make it hidden i used visibility:hidden http://jsfiddle.net/gztpsfkw/1/
i just saw that you don't want to use <img> tags but as for here the image is being hidden and it takes up the space.
<img src="http://placekitten.com/300/301" />aa
And apply the css
a{
display:block;
background-image:url('http://placekitten.com/300/301');
width:100px;
height:auto;
}
img{
visibility:hidden;
}
We can use a visibility: hidden way:
<img src="http://lorempixel.com/100/200/" />
CSS
a {background: url("http://lorempixel.com/100/200/") center center no-repeat; width: 100px;}
a img {visibility: hidden;}
Fiddle: http://jsfiddle.net/praveenscience/vhjxfgtw/
JavaScript Solution
Procedure
To set the height, dynamically, you need to use JavaScript. So, you can get the computed value by adding a <img /> tag and computing the value by setting the src. The pseudo code would have been like this:
Get the computed value of background-image.
Attach it to a new <img /> element in the DOM.
Get the height of the new <img /> element.
Set the height of the fake background <div>.
JavaScript
$(document).ready(function () {
bg = $(".bg").css("background-image");
$("body").append('<img id="faux" src="' + bg.substring(4, bg.length-1) + '" />');
height = $("#faux").outerHeight();
$("#faux").remove();
$(".bg").height(height);
});
Fiddle: http://jsfiddle.net/praveenscience/rcL3xj0x/
If you don't want to use inline CSS, you can use this:
$("style").append('.bg {height: ' + height + 'px}');
If you're looking for a way to make the background images fill all the space available then use background-size: cover
I think you're looking for something like this:
function setBackgroundImage(element, src) {
var img = new Image();
img.onload = function() {
element.style.height = img.height+'px';
element.style.backgroundImage = 'url('+img.src+')';
}
img.src = src;
}
Or, if you need to scale the images for the width:
function setImage(element, src) {
var img = new Image();
img.onload = function() {
var sizeRatio = element.offsetWidth / img.width;
element.style.height = (sizeRatio * img.height)+'px';
element.style.backgroundImage = 'url('+img.src+')';
element.style.backgroundSize = 'cover';
}
img.src = src;
}
Side Note: The <a> tag is not a block level element. In order for the <a> to have a height and a width you need to make it a block level element to show the background image.
You would use: display: block
Now for your question... In order to get the background image, with out having to manual type it in you can use a little jQUery to make your life a lot easier. I have modified your CSS and HTML a little bit to accomodate the jQuery.
CodePen Example
#links { overflow: hidden; }
#links a { display: block; float: left; width: 300px; height: 200px;
/* generic height set in case there is no background image */ }
#ex-1 { background: url('http://www.google.com/images/srpr/logo11w.png');}
#ex-2 { background: url('http://www.bing.com/s/a/hpc12.png');}
#ex-3 { background: url('http://www.google.com/images/srpr/logo11w.png');}
#ex-4 { background: url('http://www.bing.com/s/a/hpc12.png');}
<div id="links">
</div>
Here is the jquery. It will loop through all your images and set the height according to your background image
$(document).ready(function(){
$('#links a').each(function(){
var temp = $(this).css('background-image');
temp = temp.replace('url("', '').replace('")', '');
var newImg = new Image();
newImg.src = temp;
imageHeight = newImg.height;
imageWidth = newImg.width;
$(this).css('height', imageHeight);
});
});

Create soft round circles HTML5

I created circles using HTML5 Canvas. I want them to look like the soft, round brushes done with Photoshop. In this code, I can only create the circles with specific opacity:
function drawClusters(ctx) {
var startPoint = (Math.PI/180)*0;
var endPoint = (Math.PI/180)*360;
ctx.beginPath();
ctx.arc(30,30,10,startPoint,endPoint,true); // x, y, r
ctx.fillStyle = "rgb(255,255,204)";
ctx.globalAlpha = 0.5;
ctx.fill();
ctx.closePath();
}
How is it possible to achieve the soft round effect? Something like the following image:
http://jsfiddle.net/pr9r7/2/ - v2, fixed overlaping issue.
function my_circle(ctx, x, y, size, color1, color2){
var color1_rgb = hex2rgb(color1);
var color2_rgb = hex2rgb(color2);
var radgrad = ctx.createRadialGradient(
x, y, size*0,
x, y, size);
radgrad.addColorStop(0, "rgba("+color1_rgb.r+", "+color1_rgb.g+", "+color1_rgb.b+", 1)");
radgrad.addColorStop(1, "rgba("+color2_rgb.r+", "+color2_rgb.g+", "+color2_rgb.b+", 0)");
ctx.fillStyle = radgrad;
ctx.fillRect(x-size,y-size,size*2,size*2);
}
This is probably not the answer (because it does not use canvas, but plain HTML and CSS), however your question made me play a little :)
http://jsfiddle.net/n5axu/
A DIV can be styled with the box-shadow css property to get similar circles.
HTML
<div class="circle white"></div>
CSS
.circle {
height: 0;
width: 0;
box-shadow: 0 0 70px 60px;
position: fixed;
}
.circle.white { color: white; }
body { background-color: black; }

HTML vertical resizeable areas on the page

I'm trying to create a page layout like This
But I am not sure how to achieve it. What I mean; in that page you can see there are two areas in the page and you can resize the areas using the bar between them.
Thanks!
Yes, it's certainly possible. There's probably a JQuery or MooTools plugin out there that does it. Otherwise, I rolled you a simple example using JQuery that you can play with. See this JSFiddle.
Basically the HTML is like this:
<div id="left">Left column!</div>
<div id="verticalresizer"> </div>
<div id="right">Right column!</div>​
And then they are positioned absolutely (extra CSS from example cut for simplicity's sake):
html, body {
height: 100%;
}
#left {
width: 200px; /* default starting width */
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
#right {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 204px; /* width of left col + 4 pixel wide resizer */
}
#verticalresizer {
background-color: black; /* so it can be seen */
width: 4px;
height: 100%;
cursor: col-resize;
position: absolute;
top: 0;
left: 200px; /* width of left col */
bottom: 0;
}
​
Then the JavaScript. First an explanation. Pretty much the code listens for the user to click down on the vertical resizer. Once that happens, it listens for the mouse moving. Every time the mouse moves, resize the columns accordingly and keep the slider underneath the mouse. When the user lets go of the mouse (mouseup), stop listening/resizing.
var left = 200; // starting left col width
var isClicked = false;
var startX = 200; // starting horizontal position of resizer bar
var isMouseDown = false;
// attach listeners to the document itself
$(document).mousedown(function() {
isMouseDown = true;
}).mouseup(function() {
isMouseDown = false;
}).mousemove( function(event) {
if (isClicked && isMouseDown) {
var newX = event.pageX;
if (startX != newX) {
left += (newX - startX);
if (left < 0) {
left = 0; // keep from moving the slider beyond the left edge of the screen
newX = 0;
}
setWidthOfLeftColumn( left );
startX = newX;
}
}
});
// attach click listeners to the resizer slider
$("#verticalresizer").mousedown( function(event) {
isClicked = true;
startX = event.pageX;
}).mouseup( function (event) {
isClicked = false;
});
// function to resize everything
function setWidthOfLeftColumn( value ) {
$("#left").css("width", "" + left + "px");
$("#right").css("left", "" + (left + 4) + "px");
$("#verticalresizer").css("left", "" + left + "px");
}
Try using the HTML frameset tag.
http://www.w3schools.com/tags/tag_frameset.asp