I'm wondering if it's possible to reproduce this text effect:
It should appear as if the text highlights were reducing the opacity of the images. I guess what you need is a copy of the background layer getting masked in the shapes/positions of the text highlights. But is there a way to really make these masks automatically resize/reposition according to the lines of text? Or any other way to achieve the effect?
This might better explain what I'm after:
You might be looking for the css property background-attachment: fixed. This does have the caveat that the background will no longer scroll with the page and remain static, but this way you can guarantee the overlap between the element background and the container background remain the same. There is a fix for the scrolling issue via javascript, for a minor overhead cost, depending on how heavy the graphics are for the browser to render/reposition.
Then you simply apply the same background to the background containing element(.wrap in my case) and the text containing element(wrap in my case) and you get your desired effect as shown in your second image.
Then put the mark in a paragraph element and repeat the text twice. Once in the paragraph, once within the mark.
Then set the paragraph to position relative, and the mark to absolute, so they overlap each other perfectly. This is to counteract the wrap being transparent and not showing the text properly, as the text also becoming transparent.
.wrap, .wrap mark {
background-image: url('https://i.imgur.com/hAodNjT.jpg');
background-attachment: fixed;
}
.wrap p {
position: relative;
}
.wrap mark {
position: absolute;
top: 0px;
left: 0px;
opacity: 0.4;
}
img {
width: 300px;
height: auto;
}
.wrap {
padding-top:160px;
position: relative;
width: 400px;
height: 400px;
}
.wrap img {
position:absolute;
top:60px;
z-index:0;
}
.wrap p {
position:relative;
z-index: 1;
}
<div class="wrap">
<img src="https://i.imgur.com/cULI8TG.png">
<p>some text that runs over the image<mark>some text that runs over the image</mark></p>
<p>some other text that runs over the image<mark>some other text that runs over the image</mark></p>
</div>
with a background scroll fix, does introduce more overhead when scrolling
var $affected = $('.wrap, .wrap mark');
let handler = (e) => {
$affected.css({'background-position' : '-'+window.scrollX+'px -'+window.scrollY+'px'});
}
$(window).on('resize scroll', handler);
.wrap, .wrap mark {
background-image: url('https://i.imgur.com/hAodNjT.jpg');
background-attachment: fixed;
}
.wrap p {
position: relative;
}
.wrap mark {
position: absolute;
top: 0px;
left: 0px;
opacity: 0.4;
}
img {
width: 300px;
height: auto;
}
.wrap {
padding-top:160px;
position: relative;
width: 400px;
height: 400px;
}
.wrap img {
position:absolute;
top:60px;
z-index:0;
}
.wrap p {
position:relative;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<img src="https://i.imgur.com/cULI8TG.png">
<p>some text that runs over the image<mark>some text that runs over the image</mark></p>
<p>some other text that runs over the image<mark>some other text that runs over the image</mark></p>
</div>
You can use mark tag of HTML using background color with opacity:
/*custom styling of higlihter*/
mark{
background: rgba(255, 255, 255, 0.38);
color: black;
}
.wrap{
background-image: url("https://image.shutterstock.com/image-illustration/color-splash-series-background-design-260nw-587409425.jpg");
height: 230px;
width: 230px;
}
<div class="wrap">
Do <mark>not forget to buy milk today</mark>
<div>
Note: the mark tag is not supported in Internet Explorer 8 and earlier versions.
Another solution, using background and color on <p> tag with gradient:
.wrap{
background: grey;
color: white;
display: inline-block;
background:url(https://thumbs.dreamstime.com/b/halloween-background-full-moon-creepy-house-flying-bats-halloween-background-full-moon-creepy-house-125024932.jpg);
background-size: cover;
height: 200px;
width: 200px;
}
p{
font-size:20px;
background-image: linear-gradient(to right, #ffffff00, #000000c9 , #ffffff00);
text-align: center;
}
<div class="wrap"><p>Don't play with<p></div>
You can change the color accordingly.
Reference.
Related
I'm looking for a CSS solution that adapts to div contents, with the functionality of clip-path but dynamic. This is my code:
.background {
background: yellow;
text-align: center;
}
.text {
display: inline-block;
margin: 20px;
padding: 20px;
background: teal;
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
Yellow and teal are just used for illustration. I want to replace the yellow background with an image, but only show it in the teal area. The div.background spans the width of the browser, but I cannot make assumptions about the width of div.text. Can this be done with only CSS or does it require JS and dynamically setting background-position?
Use a pseudo element that you make relative to the background element
.background {
background: yellow;
text-align: center;
position: relative;
z-index: 0;
}
.text {
display: inline-block;
color: #fff;
margin: 20px;
padding: 20px;
clip-path: inset(0); /* clip to only text element */
}
.text:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: url(https://picsum.photos/id/1056/800/600) center/cover;
}
/* to illustrate */
.text:hover {
clip-path: none;
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
Here is one way of doing what you want through JS. The image is in the background element, and it is clipped according to the dimensions of the child element. There's a resize observer applied to the child element to trigger the calculation of the clipping mask whenever the dimensions of the child change.
I've added an animation to show how the clipping is calculated in real-time, but as you can see there is some slight stutter.
let text = document.querySelector('.text');
let bg = document.querySelector('.background');
let observer = new ResizeObserver(() => {
calculateClipPath(bg, text);
})
observer.observe(text);
function calculateClipPath (parent, child) {
parent.style.clipPath = `inset(
${child.offsetTop}px
${parent.clientWidth - (child.offsetLeft + child.clientWidth)}px
${parent.clientHeight - (child.offsetTop + child.clientHeight)}px
${child.offsetLeft}px
)`;
}
.background {
background: url(https://c4.wallpaperflare.com/wallpaper/368/148/1024/flowers-roses-drawing-light-wallpaper-preview.jpg);
text-align: center;
position: relative;
}
.text {
display: inline-block;
margin: 20px;
padding: 40px;
width: 200px;
animation: 3s infinite change;
}
#keyframes change {
0% {
width: 200px;
}
50% {
width: 150px;
}
100% {
width: 200px;
}
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
I'm still experimenting to see if there is a purely CSS version of the solution because that would always be smoother than the JS solution. If I can figure it out, I'll edit this answer and add it here
I want to add rgba(0,0,0,0.25) on top of backgroundColor: "#0075FF" to make it darker. However is there any way to achieve it without using a mixed color value? Note: I also would like to avoid an approach that has an overlaid element on top of it.
You can use a this trick with linear gradients:
background: linear-gradient(#f005, #f005), linear-gradient(#0f05, #0f05);
In this way you are using two gradients with alpha. The trick is that the colours of gradients starts and ends with the same value.
You can do a pure CSS approach, although it sort of overlays a pseudo-element on top of the main element.
*Try hovering over the example.
.colored {
background: #0075FF;
width: 100px;
height: 100px;
position: relative;
}
.colored:hover:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.25);
}
<div class="colored"></div>
You can always make a separate container, place the elements in it, then in css make the new container the same size as the one you want to place on the other. I used a low opacity so you can see through the top color, making it look purple when it isn't.
You gain adjust the size of the container and then use placement methods as you wish.
.main {
width: 200px;
height: 200px;
background: red;
}
.img {
background-color: blue;
width: 200px;
height: 200px;
z-index: 2;
opacity: .5;
}
<div class="main">
<div class="img"></div>
</div>
You can use a :before pseudo element.
<div className="container">
....content
</div>
.container {
position: relative;
background-color: #0075FF;
}
.container:before {
content:"";
display:block;
position: absolute;
height: 100%;
width: 100%;
top: 0px;
left: 0px;
background-color: rgba(0,0,0,0.25);
}
I want to apply a background-color on an image to put a shadow on it.
Nothing very peculiar for now, I simply put background-color:rgba(23,23,23,0.88); in my CSS.
But on this image, I need to have an other div, who display the real image without the shadow on it and I don't know how I can do it.
I made a fiddle because it must not be very clear: https://jsfiddle.net/Haplo31/aguxfr67/
In this fiddle, I would need to have the blue div "content" displaying the part of the image below without the background-color of the bgContainer, like a window on the image. (I don't need the blue color at all, it's just to highlight the div for the example)
Is this possible?
Thanks a lot for your time and your help
You could be using the box-shadow property, which comes in pretty handy in situations like this. I modified your bg-container class and added a :before selector to apply the shadow.
Text can be inserted through the content css-attribute, you could also create another div-class, apply the same positioning properties and fuel your text into that.
.imgContainer {
background-image: url('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoR1aeLhVEeg-rfmWln8uuNI7t0El3zNY8HHfKT1Qwd2oN8-GPQQ');
background-size: cover;
width: 300px;
height: 200px;
}
.bgContainer {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.bgContainer:before {
content: 'This is some sample text to demonstrate you can get content as well';
color: white;
padding: 5px;
width: 50%;
height: 50%;
position: absolute;
bottom: 25%;
right: 25%;
box-shadow: 0 0 0 300px black;
opacity: 0.88;
}
.content {
width: 100px;
height: 100px;
top: 100px;
background-color: blue;
}
<div class="imgContainer">
<div class="bgContainer">
<!--<div class="content">
</div>-->
</div>
</div>
I know that it is impossible to actually modify an image with CSS, which is why I put crop in quotes.
What I'd like to do is take rectangular images and use CSS to make them appear square without distorting the image at all.
I'd basically like to turn this:
Into this:
A pure CSS solution with no wrapper div or other useless code:
img {
object-fit: cover;
width: 230px;
height: 230px;
}
Assuming they do not have to be in IMG tags...
HTML:
<div class="thumb1">
</div>
CSS:
.thumb1 {
background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
width: 250px;
height: 250px;
}
.thumb1:hover { YOUR HOVER STYLES HERE }
EDIT: If the div needs to link somewhere just adjust HTML and Styles like so:
HTML:
<div class="thumb1">
Link
</div>
CSS:
.thumb1 {
background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
width: 250px;
height: 250px;
}
.thumb1 a {
display: block;
width: 250px;
height: 250px;
}
.thumb1 a:hover { YOUR HOVER STYLES HERE }
Note this could also be modified to be responsive, for example % widths and heights etc.
If the image is in a container with a responsive width:
.rect-img-container {
position: relative;
}
.rect-img-container::after {
content: "";
display: block;
padding-bottom: 100%;
}
.rect-img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="rect-img-container">
<img class="rect-img" src="https://picsum.photos/id/0/367/267" alt="">
</div>
(edit: updated from sass to plain css)
(edit: Added dummy image for reference)
Place your image in a div.
Give your div explicit square dimensions.
Set the CSS overflow property on the div to hidden (overflow:hidden).
Put your imagine inside the div.
Profit.
For example:
<div style="width:200px;height:200px;overflow:hidden">
<img src="foo.png" />
</div>
Using background-size:cover - http://codepen.io/anon/pen/RNyKzB
CSS:
.image-container {
background-image: url('http://i.stack.imgur.com/GA6bB.png');
background-size:cover;
background-repeat:no-repeat;
width:250px;
height:250px;
}
Markup:
<div class="image-container"></div>
I actually came across this same problem recently and ended up with a slightly different approach (I wasn't able to use background images). It does require a tiny bit of jQuery though to determine the orientation of the images (I' sure you could use plain JS instead though).
I wrote a blog post about it if you are interested in more explaination but the code is pretty simple:
HTML:
<ul class="cropped-images">
<li><img src="http://fredparke.com/sites/default/files/cat-portrait.jpg" /></li>
<li><img src="http://fredparke.com/sites/default/files/cat-landscape.jpg" /></li>
</ul>
CSS:
li {
width: 150px; // Or whatever you want.
height: 150px; // Or whatever you want.
overflow: hidden;
margin: 10px;
display: inline-block;
vertical-align: top;
}
li img {
max-width: 100%;
height: auto;
width: auto;
}
li img.landscape {
max-width: none;
max-height: 100%;
}
jQuery:
$( document ).ready(function() {
$('.cropped-images img').each(function() {
if ($(this).width() > $(this).height()) {
$(this).addClass('landscape');
}
});
});
Check out CSS aspect-ratio
https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
.square-image{
width: 50%;
background-image: url('https://picsum.photos/id/0/367/267');
background-size: cover;
background-position: center;
aspect-ratio: 1/1;
}
<div class="square-image"></div>
You can also do this with a regular img tag as follows
.square-image{
width: 50%;
object-fit: cover; /* Required to prevent the image from stretching, use the object-position property to adjust the visible area */
aspect-ratio: 1/1;
}
<img src="https://picsum.photos/id/0/367/267" class="square-image"/>
Today you can use aspect-ratio:
img {
aspect-ratio: 1 / 1;
}
It has wide support amongst modern browsers as well:
https://caniuse.com/mdn-css_properties_aspect-ratio
object-fit: cover will do exactly what you need.
But it might not work on IE/Edge. Follow as shown below to fix it with just CSS to work on all browsers.
The approach I took was to 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%);
Once it is in the centre, I give to the image,
// 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/
This logic works in all browsers.
Original Image
Vertically Cropped
Horizontally Cropped
Square Container
I had a similar issue and could not "compromise" with background images.
I came up with this.
<div class="container">
<img src="http://lorempixel.com/800x600/nature">
</div>
.container {
position: relative;
width: 25%; /* whatever width you want. I was implementing this in a 4 tile grid pattern. I used javascript to set height equal to width */
border: 2px solid #fff; /* just to separate the images */
overflow: hidden; /* "crop" the image */
background: #000; /* incase the image is wider than tall/taller than wide */
}
.container img {
position: absolute;
display: block;
height: 100%; /* all images at least fill the height */
top: 50%; /* top, left, transform trick to vertically and horizontally center image */
left: 50%;
transform: translate3d(-50%,-50%,0);
}
//assuming you're using jQuery
var h = $('.container').outerWidth();
$('.container').css({height: h + 'px'});
Hope this helps!
Example:
https://jsfiddle.net/cfbuwxmr/1/
Use CSS: overflow:
.thumb {
width:230px;
height:230px;
overflow:hidden
}
Either use a div with square dimensions with the image inside with the .testimg class:
.test {
width: 307px;
height: 307px;
overflow:hidden
}
.testimg {
margin-left: -76px
}
or a square div with a background of the image.
.test2 {
width: 307px;
height: 307px;
background: url(http://i.stack.imgur.com/GA6bB.png) 50% 50%
}
Here's some examples: http://jsfiddle.net/QqCLC/1/
UPDATED SO THE IMAGE CENTRES
.test {
width: 307px;
height: 307px;
overflow: hidden
}
.testimg {
margin-left: -76px
}
.test2 {
width: 307px;
height: 307px;
background: url(http://i.stack.imgur.com/GA6bB.png) 50% 50%
}
<div class="test"><img src="http://i.stack.imgur.com/GA6bB.png" width="460" height="307" class="testimg" /></div>
<div class="test2"></div>
I came with a different approach. You basically have to crop the rectangular image to fit it inside the square is all there is to it. Best approach is if the image width is greater than the height, then you crop the image alittle from left and right side of the image. If the image height is greater than the image width then you crop the bottom of the image. Here is my solution. I needed a little help from PHP though.
<div style="position: relative; width: 154px; height: 154px; overflow: hidden;">
<?php
//get image dimmensions whichever way you like. I used imgaick
$image = new Imagick("myimage.png");
$width = $image->getImageWidth();
$height = $image->getImageHeight();
if($width > $height){
?>
<img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 50%; transform: translateX(-50%); -ms-transform: translateX(-50%); -webkit-transform: translateX(-50%); height: 100%; " />
<?php
}else{
?>
<img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 0px; width: 100%; " />
<?php
}
?>
</div>
Normally, you center images with display: block; margin: auto, but if the image is larger than the container, it overflows to the right. How do I make it overflow to the both sides equally? The width of the container is fixed and known. The width of the image is unknown.
A pure css solution
Requiring one extra wrapper (tested in FireFox, IE8, IE7):
Improved Answer
There was a problem with the original answer (below). If the image is larger than the container that outer is centered on with it's auto margins, then it truncates the image on the left and creates excessive space on the right, as this fiddle shows.
We can resolve that by floating inner right and then centering from the right. This still truncates the img off the page to the left, but it does so by explicitly pushing it that way and then centers back off of that, the combination of which is what prevents the extra horizontal scroll on the right. Now we only get as much right scroll as we need in order to see the right part of the image.
Fiddle Example (Borders in fiddle are for demo only.)
Essential CSS
div.outer {
width: 300px; /* some width amount needed */
margin: 0 auto;
overflow: visible;
}
div.inner {
position:relative;
float: right; /* this was added and display removed */
right: 50%;
}
div.inner img {
position: relative;
right:-50%; /* this was changed from "left" in original */
}
If you desire no right scroll at all for wide images
Then using the above, also set whatever element wraps outer (like body or a third wrapper) to have overflow: hidden.
Original Idea (for History)
Fiddle Example (Borders in fiddle are for demo only.)
HTML
<div class="outer">
<div class="inner">
<img src="/yourimage.png">
</div>
</div>
CSS
div.outer {
width: 300px; /* some width amount needed */
margin: 0 auto;
overflow: visible;
}
div.inner {
display: inline-block;
position:relative;
right: -50%;
}
div.inner img {
position: relative;
left:-50%;
}
Here's a 2 line CSS solution (a couple more lines might be required for cross-browser support):
img {
margin-left: 50%;
transform: translateX(-50%);
}
HTML
<div class="image-container">
<img src="http://www.google.com/images/logo.gif" height="100" />
</div>
CSS
.image-container {
width: 150px;
border: solid 1px red;
margin:100px;
}
.image-container img {
border: solid 1px green;
}
jQuery
$(".image-container>img").each(function(i, img) {
$(img).css({
position: "relative",
left: ($(img).parent().width() - $(img).width()) / 2
});
});
See it on jsFiddle: http://jsfiddle.net/4eYX9/30/
Alternative pure CSS solution is to use transform attribute:
HTML:
<div class="outer">
<img class="image" src="http://www.gstatic.com/webp/gallery/4.jpg" />
</div>
CSS:
.outer {
position: relative;
width: 100px;
border: 1px solid black;
height: 150px;
margin-left: 100px; /* for demo */
/* overflow: hidden; */
}
img.image {
width: 200px;
opacity: 0.7;
position: absolute;
left: 50%;
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
}
Fiddle
Just to add a overflow:hidden to parent div to hide the extra area of the image.
Your best bet is to set it as background image of the container instead.
#container {
background: url('url/to/image.gif') no-repeat center top;
}
In fact there is a simpler pure css/html way (without large horizontal scroll) :
Html :
<div class="outer">
<img src="/my/sample/image.jpg">
</div>
Css :
If you don't want to see image overflow
div.outer img {
position: absolute;
left: -50%;
z-index:-1;
}
div.outer {
overflow: hidden;
position: relative;
height: 200px;
}
With image overflow visible
div.outer img {
position: absolute;
left: -50%;
z-index:-1;
}
div.outer {
overflow: visible;
position: relative;
height: 200px;
}
body, html {
overflow-x:hidden;
}
A background solution with image overflow visible :
Html :
<div class="outer">
<div class="inner"></div>
</div>
Css :
div.outer {
width: 100%;
height: 200px;
}
div.inner {
background: url('/assets/layout/bg.jpg') center no-repeat;
position: absolute;
left: 0;
width: 100%;
height: inherit;
}
assuming outer is in a width specified container.
I see this is an old post, so maybe everybody knows this by now, but I needed help for this and I solved it using flex:
.parent {
display: flex;
/* give it the width and height you like */
}
.parent img {
min-width: 100%;
min-height: 100%;
object-fit: cover;
}
I can only think of a Javascript solution since what you need to do is relatively position the image a negative amount to the left of its container:
jQuery
$(document).ready(function(){
var theImg = $('#container img');
var theContainer = $('#container');
if(theImg.width() > theContainer.width()){
theImg.css({
position: 'relative',
left: (theContainer.width() - theImg.width()) / 2
})
}
})
I found this to be a more elegant solution, without flex, similar to something above, but more generalized (applies on both vertical and horizontal):
.wrapper {
overflow: hidden;
}
.wrapper img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* height: 100%; */ /* optional */
}
I don't think there is a pure CSS solution (Except for the next answer :)). However with Javascript it would be just a matter of finding the width of the image, subtracting the container width, dividing by two and you have how far to the left of the container you need.