background image not showing in Angular - css

Yes, I did search and found many examples, but none worked for me. I am not sure what am I doing wrong. Need help!
I can see the image if I put in <img> tag, but not when I put as background-image. But I can see the binary image when I do inspect element.
Tried doing an example in stackblitz
https://stackblitz.com/edit/display-image-from-rest-api-qpnspq?embed=1&file=src/app/app.component.ts
HTML:
<!-- This works -->
<div class="row" style="max-width: 100%; margin-left: 1px;" >
<img id="dashboardImage" [src]='imageBlobDataUrl' height='500' width='500' />
</div>
<!-- This does NOT works -->
<div class="row" style="max-width: 100%; margin-left: 1px;" [style.background-image]="image"> </div>
TS:
#Input() imageBlobDataUrl: any;
selectedImage: QiImage = new QiImage();
public header:SafeHtml;
public content:SafeHtml[];
public image:SafeStyle;
constructor(
private qiImageService: QiImageService,
private sanitizer: DomSanitizer,
private imageService: ImageService
) {}
populateImageDetails(lineId, bitmapFileName) {
this.imageService
.populateImageDetails(lineId, bitmapFileName)
.subscribe( (selectedImage : any) => {
this.selectedImage = selectedImage;
//let TYPED_ARRAY = new Uint8Array(selectedImage.imageData);
//const STRING_CHAR = String.fromCharCode.apply(null, TYPED_ARRAY);
//let base64String = btoa(STRING_CHAR);
let objectURL = 'data:image/png;base64,' + selectedImage.imageData;
this.imageBlobDataUrl = this.sanitizer.bypassSecurityTrustUrl(objectURL);
this.image = this.sanitizer.bypassSecurityTrustStyle(`url(${objectURL})`);
});
}

It works fine when i tried your stackblitz . You need to Fix CSS to get the image displayed on view.
Do not use bypassSecurityTrustUrl for Style Url. So the below for thumbnail is not valid:
this.thumbnail = this.sanitizer.bypassSecurityTrustUrl(objectURL); // Do NOT Use
this.image = this.sanitizer.bypassSecurityTrustStyle(`url(${objectURL})`); // This works fine and is Valid
Try to adjust the CSS position for your image and it will show up:
<div class="row"
style="width: 100%; height: 100%; position:absolute;
margin-left: 1px; background-repeat: no-repeat;"
[style.background-image]="image"> </div>

if you try to set the background image using CSS ? like this:
.bg {
background-image: url("../../yourimage");
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
}
In the template you can use the binding to set the css class as you like

You can just put the URL image on src even if it's on base64
<img id="dashboardImage" [src]='objectURL' height='500' width='500' />

Related

Make text overflow visible on hover using react, CSS

I have an array of divs containing book names that I generate using a .map function on some fetched data from my database. Some of the book names are too long so I have used the following CSS to hide them:
.book-title{
font-weight: 600;
height: 1.5rem;
max-width: 15rem;
overflow: hidden;
padding-top: 0.7rem;
}
But I would like to make the text visible when user hovers over the div. My current solution applies to all divs generated and displayed by the .map function - I am unsure how to make it just apply to divs where the text is too long.
.book-title:hover{
height: 6rem;
overflow: visible;
}
Is there a proper way to do this with react?
here is the relevant .jsx
const listsForFrontPage = listArray.map((book, id) => {
return (
<Link className="book-link" to={`/books/${book.book_id}`} key={id}>
<div className="book-card">
<div className="book-card-image">
<img
className="cover-image"
src={book.cover_image}
alt="The book cover"
/>
</div>
<div className="book-info">
<div className="book-title">{book.title}</div>
<div className="author-name">{book.name}</div>
</div>
</div>
</Link>
)
})
You need to check if the element is overflowing
add useRef:
const refs = useRef(listArray.map(() => React.createRef()));
then you should create a function that checks if the element is overflowing:
const isOverflown = (el) => {
if(!el) return;
const { clientWidth, clientHeight, scrollWidth, scrollHeight } = el;
return scrollHeight > clientHeight || scrollWidth > clientWidth;
}
and then you need to add class based on isOverflown value:
const listsForFrontPage = listArray.map((book, id) => {
return (
<Link className="book-link" to={`/books/${book.book_id}`} key={id}>
<div className="book-card">
<div className="book-card-image">
<img
className="cover-image"
src={book.cover_image}
alt="The book cover"
/>
</div>
<div className="book-info">
<div ref={refs.current[id]} className={`book-title ${isOverflown(refs.current[id].current) ? 'book-title-overflow' : ''}`}>{book.title}</div>
<div className="author-name">{book.name}</div>
</div>
</div>
</Link>
)
})
don't forget to add your css:
.book-title-overflow:hover{
height: 6rem;
overflow: visible;
}

React onMouseEnter/onMouseLeave used to hover in a map

I'm currently working on a dating website for a school project, but i'm stuck and not sure if i'm on the right way.
On the user profile, i want a list of the photos the user choose to show, and i want a hover on the photo where the pointer is.
In my state i added a listPhotoHover: [ ], a tab that contains variables true or false. listPhotoHover[0] = true means the first photo of the list has a hover, false means no hover.
I map and add a div for every photo with a onMouseEnter( ) that takes the photo index and set it an hover if fired.
The hover appears if listPhotoHover[index] exists, the hover div has an onMouseLeave( ) that takes the photo index and set the hover of the photo as false.
Everything seems to work but i'm not sure if it's the best way to do it, and when i move very fast on every photo the hover is still there i think the onMouseLeave( ) don't run.
Here's my code
Map of every photo :
photos.map((photo, index) => {
return
<div className={`flex row`} key={index} >
<img
className={classes.userPhotos}
src={photo}
alt={`photo de ${name}`}
onMouseEnter={() => { this.haveHover(index) }}
/>
{
listPhotoHover[index]
? <div
className={`
absolute flex center alignCenter
${classes.userPhotos} ${classes.photoHover}
`}
onMouseLeave={
() => { this.removeHover(index) }
}
/>
: null
}
</div>
})
function when onMouseEnter() or onMouseLeave() is fired:
haveHover (index, value) {
const tab = this.state.listPhotoHover
tab[index] = value
this.setState({listPhotoHover: tab})
}
I would like to know why does the onMouseLeave() don't work when my pointer move very fast and also what is the best way to do an hover on a map.
Thank you for your advices and sorry if i don't write english correctly
ps: i checked previous questions and didn't find any answer yet :(
Josephine
I don't believe you need javascript to achieve your desired effect. If it is simply to show something when the image is hovered, you can uses some advanced CSS selectors to do this. Run the snippet below to
html {
font-family: sans-serif;
font-size: 10px;
}
.wrap {
position: relative;
}
.image {
width: 80px;
height: 80px;
}
.imageinfo {
display: none;
width: 80px;
height: 17px;
background: #cc0000;
color: #efefef;
padding: 3px;
text-align: center;
box-sizing: border-box;
position: absolute;
bottom: -13px;
}
/* here's the magic */
.image:hover+.imageinfo {
display: block;
}
Hover the image to see the effect
<div class="wrap">
<img class="image" src="https://www.fillmurray.com/80/80" />
<div class="imageinfo">
Bill Murray FTW
</div>
</div>
I just realized i did it all wrong, i added a className with a '&:hover' on the div containing one photo, and it works. No need javascript :D
I don't know why i wanted to complicate it haha..
className:
ANSWER: {
'&:hover': {
opacity: '0.4',
cursor: 'pointer'
}
}
div with the photo:
photos.map((photo, index) => {
return <div className={`flex row ${classes.ANSWER}`} key={index} >
<img
className={classes.userPhotos}
src={photo}
alt={`${name}`}
/>
</div>
})
Hope my mistake will help some people

How to have an anim gif on a link and play it on hover and reset

First of all many thanks for this page, it has been helping me a lot! But at this point I have a question where I cannot find an answer that fits what I want (maybe it cannot be achieved the way I am doing it).
I want to have a link with a static image, and when the user moves the cursor over the link I want an animated gif to play (the anim gif is set to not loop, so it only plays once). And when the user moves out go back to the static image and if the user goes in again, the gif should play again from the beginning.
I am using html5 combined with CSS to create my web (which I am using to learn at the same time). I did programing in the past with C++ and similar, but never on a web context.
So far this is what I tried:
CSS:
.img-acu
{
float: left;
width: 450px;
height: 264px;
background:transparent url("acu.gif") center top no-repeat;
}
.img-acu:hover
{
background-image: url("acusel.gif");
}
HTML:
But nothing at all appears :(
The weird thing is, I used this same example with two static images (png format) and it worked fine, but for some reason with the animated gif it doesn't want to work.
The I tried this:
CSS:
#test
{
width: 450px;
height: 264px;
background-image: url("acu.gif");
background-repeat: no-repeat;
background-position: left;
margin-left: 75px;
}
#test:hover
{
background-image: url("acusel.gif");
}
HTML:
<div id="test"></div>
And that works perfectly, it is just the link doesn't work and when the animated gif reaches the last frame, it never resets (unless I reload the page).
Do you know if there is any way to achieve this properly in HTML5 + CSS? should I use javascript or php?
I would really appreciate any help!
Thanks a lot!!
That can be achieved by use a static image and your gif image(Hey, that how 9gag do it!)
A basic script could be somthing like that:
<img id="myImg" src="staticImg.png" />
<script>
$(function() {
$("#myImg").hover(
function() {
$(this).attr("src", "animatedImg.gif");
},
function() {
$(this).attr("src", "staticImg.jpg");
}
);
});
</script>
Hopefully this simple way can help someone:
<img class="static" src="https://lh4.googleusercontent.com/-gZiu96oTuu4/Uag5oWLQHfI/AAAAAAAABSE/pl1W8n91hH0/w140-h165-no/Homer-Static.png"><img class="active" src="https://lh4.googleusercontent.com/i1RprwcvxhbN2TAMunNxS4RiNVT0DvlD9FNQCvPFuJ0=w140-h165-no">
Then add the following CSS:
.static {
position: absolute;
background: white;
}
.static:hover {
opacity: 0;
}
This should hopefully help some people. I got the code from a codepen and decided some stack overflow users may find it helpful. If you would like to view the original codepen, visit here: CodePen
The approach you took did not work because CSS will not change the background on < a >. Solving this can be done entirely with vanilla JS + HTML. The trick is to place:
<div class="img-acu">
inside of:
(insert here)
All that's left is to have CSS target the div. That way, you can set the static background, which then changes on :hover
Here's a fiddle showing this in action (or you can fiddle with this: https://jsfiddle.net/lyfthis/yfmhd1xL/):
.img-acu
{
float: left;
width: 250px;
height: 132px;
background:transparent url("https://i.imgur.com/7r91PY3.jpeg") center top no-repeat;
background-size: 125%;
}
.img-acu:hover
{
background-image: url("https://media.giphy.com/media/QMkPpxPDYY0fu/giphy.gif");
}
<!-- Don't do this:
-->
<div>
<div>Click on image below to go to link:</div>
<a href="https://www.google.com" title="ACU Project link">
<div class="img-acu"></div>
</a>
</div>
Try this if you are OK to use canvas:
<!DOCTYPE html>
<html>
<head>
<style>
.wrapper {position:absolute; z-index:2;width:400px;height:328px;background-color: transparent;}
.canvas {position:absolute;z-index:1;}
.gif {position:absolute;z-index:0;}
.hide {display:none;}
</style>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script>
window.onload = function() {
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var img = document.getElementById("gif");
ctx.drawImage(img, 0, 0);
}
$(document).ready(function() {
$("#wrapper").bind("mouseenter mouseleave", function(e) {
$("#canvas").toggleClass("hide");
});
});
</script>
</head>
<body>
<div>
<img id="gif" class="gif" src="https://www.macobserver.com/imgs/tips/20131206_Pooh_GIF.gif">
<canvas id="canvas" class="canvas" width="400px" height="328px">
Your browser does not support the HTML5 canvas tag.
</canvas>
<div id="wrapper" class="wrapper"></div>
</div>
</body>
</html>

Placeholder background/image while waiting for full image to load?

I have a few images on my page. I'm finding that the page starts to render before the images have been loading (which is good), but that the visual effect is not great. Initially the user sees this:
--------hr--------
text
Then a few milliseconds later the page jumps to show this:
--------hr--------
[ ]
[ image ]
[ ]
text
Is there a simple way that I can show a grey background image of exactly the width and height that the image will occupy, until the image itself loads?
The complicating factor is that I don't know the height and width of the images in advance: they are responsive, and just set to width: 100% of the containing div. This is the HTML/CSS:
<div class="thumbnail">
<img src="myimage.jpeg" />
<div class="caption">caption</div>
</div>
img { width: 100% }
Here's a JSFiddle to illustrate the basic problem: http://jsfiddle.net/X8rTB/3/
I've looked into things like LazyLoad, but I can't help feeling there must be a simpler, non-JS answer. Or is the fact that I don't know the height of the image in advance an insurmountable problem? I do know the aspect ratio of the images.
Instead of referencing the image directly, stick it within a DIV, like the following:
<div class="placeholder">
<div class="myimage" style="background-image: url({somedynamicimageurl})"><img /></div>
</div>
Then in your CSS:
.placeholder {
width: 300;
height: 300;
background-repeat: no-repeat;
background-size: contain;
background-image: url('my_placeholder.png');
}
Keep in mind - the previous answers that recommend using a div background approach will change the semantic of your image by turning it from an img into a div background. This will result in things like no indexing of these images by a search crawler, delay in loading of these images by the browser (unless you explicitly preload them), etc.
A solution to this issue (while not using the div background approach) is to have a wrapper div to your image and add padding-top to it based on the aspect ratio of the image that you need to know in advance. The below code will work for an image with an aspect ratio of 2:1 (height is 50% of width).
<div style="width:100%;height:0; padding-top:50%;position:relative;">
<img src="<imgUrl>" style="position:absolute; top:0; left:0; width:100%;">
</div>
Of course - the major disadvantage of this approach is that you need to know the aspect ratio of the image in advance.
There is a really simple thing to check before you start looking into lazy-loading and other JavaScript. Make sure the JPEG images you are loading are saved with the 'progressive' option enabled!
This will cause them to load the image iteratively, starting with a placeholder that is low-resolution and faster to download, rather than waiting for the highest resolution data before rendering.
It's very simple...
This scenario allows to load a profile photo that defaults to a placeholder image.
You could load multi CSS background-image into an element. When an avatar photo fails, the placeholder image appears default of div.
If you're using a div element that loads via a CSS background-image, you could use this style:
#avatarImage {
background-image: url("place-holder-image.png"), url("avatar-image.png");
}
<div id="avatarImage"></div>
Feel free to copy this:
<script>
window.addEventListener("load", function () {
document.getElementById('image').style.backgroundColor = 'transparent';
});
</script>
<body>
<image src="example.example.example" alt="example" id="image" style="background-color:blue;">
</body>
I got this from here: Preloader keeps on loading and doesnt disappear when the content is loaded.
Apart from all solutions already mentioned, the last solution would be to hide the document until everything is loaded.
window.addEventListener('load', (e) => {
document.body.classList.add('loaded');
});
body {
opacity: 0;
}
body.loaded {
opacity: 1;
}
<div id="sidebar">
<img src="http://farm9.staticflickr.com/8075/8449869813_1e62a60f01_b.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-1.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-2.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-3.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-4.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-5.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-6.jpg" />
</div>
Or show some animation while everything is loading:
window.addEventListener('load', (e) => {
document.body.classList.add('loaded');
});
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 70px;
height: 70px;
-webkit-animation: spin 2s linear infinite;
/* Safari */
animation: spin 2s linear infinite;
position: absolute;
left: calc(50% - 35px);
top: calc(50% - 35px);
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
body :not(.loader) {
opacity: 0;
}
body .loader {
display: block;
}
body.loaded :not(.loader) {
opacity: 1;
}
body.loaded .loader {
display: none;
}
<div class="loader"></div>
<div id="sidebar">
<img src="http://farm9.staticflickr.com/8075/8449869813_1e62a60f01_b.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-1.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-2.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-3.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-4.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-5.jpg" />
<img src="https://www.nla.gov.au/sites/default/files/pic-6.jpg" />
</div>
The only thing I can think of, to minimize the jump effect on your text, is to set min-height to where the image will appear, I would say - set it to the "shorter" image you know of. This way the jump will be less evident and you won't need to use lazyLoad or so... However it doesn't completely fix your problem.
Here's one naive way of doing it,
img {
box-shadow: 0 0 10px 0 rgba(#000, 0.1);
}
You can manipulate the values, but it creates a very light border around the image that doesn't push the contents. Images can load at whatever time they want, and you get a good user experience.
Here is what I did with Tailwind CSS, but it's just CSS:
img {
#apply bg-no-repeat bg-center;
body.locale-en & {
background-image: url("data:image/svg+xml;utf8,<svg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'><text x='50%' y='50%' style='font-family: sans-serif; font-size: 12px;' dominant-baseline='middle' text-anchor='middle'>Loading…</text></svg>");
}
body.locale-fr & {
background-image: url("data:image/svg+xml;utf8,<svg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'><text x='50%' y='50%' style='font-family: sans-serif; font-size: 12px;' dominant-baseline='middle' text-anchor='middle'>Chargement…</text></svg>");
}
}
You can find the width and height of the images in the developer tools console, for example in Chrome you can click the cursor icon in the developer tools console and when you hover on the page it will highlight all the properties of the elements in the page.
This will help you find the width and height of the images, because if you hover on top of your images it will give you the dimensions of the image and other more properties. You can also make an individual div for each image and make the div relative to the images width and height. You can do it like this:
The main div will contain the images and also the background-div which is below the image.
HTML:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class=".mainDiv">
<div class="below"></div>
<img src="https://imgix.bustle.com/uploads/image/2020/2/13/da1a1ca4-95ec-40ea-83c1-4f07fac8b9b7-eqb9xdwx0auhotc.jpg" width="500"/>
</div>
</body>
</html>
CSS:
.mainDiv {
position: relative;
}
.below {
position: absolute;
background: #96a0aa;
width: 500px;
height: 281px;
}
img {
position: absolute;
}
The result will be that .below will be below the image and so when the image has trouble loading the user will instead see the grey .below div. You cannot see the .below div because it is hidden below the image. The only time you will see this is when the loading of the image is delayed. And this will solve all your problems.
I have got a way. But you will need to use JavaScript for it.
The HTML:
img = document.getElementById("img")
text = document.getElementById("text")
document.addEventListener("DOMContentLoaded", () => {
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAA1BMVEWIiIhYZW6zAAAASElEQVR4nO3BgQAAAADDoPlTX+AIVQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwDcaiAAFXD1ujAAAAAElFTkSuQmCC";
text.innerHTML = "Loaded but image is not";
});
window.onload = function() {
img.src = "https://media.geeksforgeeks.org/wp-content/uploads/20190913002133/body-onload-console.png";
text.innerHTML = "Image is now loaded";
};
#img {
width: 400px;
height: 300px;
}
<hr>
<img id="img" src="https://media.geeksforgeeks.org/wp-content/uploads/20190913002133/body-onload-console.png">
<p>Here is the Image</p>
<p id="text">Not Loaded</p>

Image not loading in chrome from css background property

I am using "background: #BDBDBD url(image.png) top left no-repeat" this css property for two div elements which has width and height set. On clicking a button I am changing the width of both the nested divs dynamically by making the function run continuously with the help of setInterval(). The image is not loading in chrome but it works fine in firefox and IE .. Many searches convey that using background image in chrome is not working but none of those solutions seems to work.
<div id="boxes">
<div id="dialog" class="window" style="overflow: auto">
<div id="progressBar" class="meter-wrap" style="display: block;position: relative; margin: auto;">
<div class="meter-value" style="background-color: #05C; width: 40%">
<div class="meter-text">
Loading...
</div>
</div>
</div>
<div class="meter-text-message">
Loading...
</div>
</div>
CSS:
.meter-wrap, .meter-value, .meter-text {
width: 155px; height: 30px;
}
.meter-wrap, .meter-value {
background: #bdbdbd url('/sf-images/tracker/inline_progress_bar.png') top left no-repeat;
}
js code:
function setProgressBar() {
var pgBar = jQuery("#progressBar");
pgBar.show();
running = true;
var inter = null;
function run() {
pgBar.find(".meter-value").css("width", progress + "%");
pgBar.find(".meter-text").text(progress + "%");
if (progress == 100) {
jQuery(".meter-text-message").html("Complete");
clearInterval(inter);
running = false;
}
}
inter = setInterval(run, 50);
}
Found that the image is not loading for first time, I made the div element visible with the image as background by another method. After that , when I execute the above js method image loads properly.

Resources