Jpg backup option for webP using Background-image? - css

I am using Vue for my project. A lot of my images are done using background-image.
<div :style="`background:url('${user.image});`"></div>
According to google if I am using an I can setup:
<picture>
<source srcset="img/awesomeWebPImage.webp" type="image/webp">
<source srcset="img/creakyOldJPEG.jpg" type="image/jpeg">
<img src="img/creakyOldJPEG.jpg" alt="Alt Text!">
</picture>
Is there a way to do something similar for background-image?

There is no truly CSS only solution, you'd have to rely on javascript for this.
The best is probably to have a 1x1px webp image and try to load it to then set a flag.
Unfortunately (?) this process is asynchronous.
function testWebPSupport() {
return new Promise( (resolve) => {
const webp = "data:image/webp;base64,UklGRkAAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAIAAAAAAFZQOCAYAAAAMAEAnQEqAQABAAFAJiWkAANwAP79NmgA";
const test_img = new Image();
test_img.src = webp;
test_img.onerror = e => resolve( false );
test_img.onload = e => resolve( true );
} );
}
(async ()=> {
const supports_webp = await testWebPSupport();
console.log( "this browser supports webp images:", supports_webp );
// for stylesheets
if( !supports_webp ) {
document.body.classList.add( 'no-webp' );
}
// for inline ones, just check the value of supports_webp
const extension = supports_webp ? 'webp' : 'jpg';
// elem.style.backgroundImage = `url(file_url.${ extension })`;
})();
.bg-me {
width: 100vw;
height: 100vh;
background-image: url(https://upload.wikimedia.org/wikipedia/commons/9/98/Great_Lakes_from_space_during_early_spring.webp);
background-size: cover;
}
.no-webp .bg-me {
/* fallback to png */
background-image: url(https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Great_Lakes_from_space_during_early_spring.webp/800px-Great_Lakes_from_space_during_early_spring.webp.png);
}
<div class="bg-me"></div>

Related

Prevent Angular 15 iframe update browser history

I have an Angular 15 app with an iframe where I render html content from file.
Since this content may be changed by user I update src value. This affects browser history stack.
I was googling and found here Angular 7 iframe history back button trouble how to solve the issue. There is only one problem. My src variable is base64 content.
This is what I was using before and it renders fine but affects location stack:
.html
<div class="form-data">
<iframe width="100%" height="100%" [src]="layoutPath"></iframe>
</div>
.ts
private dbLayout: string;
layoutPath: SafeHtml;
ngOnInit() {
this.myService.getLayoutFromApi$().subscribe(result => this.dbLayout = result);
}
userChangeSomeContentOfHtml(someUserContent: string) {
const base64Layout = Base64.encode(dbLayout+ someUserContent);
this.layoutPath = this.sanitizer.bypassSecurityTrustResourceUrl("data:text/html;base64," + base64Layout);
}
}
According to solution from above link I updated my code to this:
.html
<div class="form-data">
<iframe #iframe width="100%" height="100%"></iframe>
</div>
.ts
private dbLayout: string;
ngOnInit() {
this.myService.getLayoutFromApi$().subscribe(result => this.dbLayout = result);
}
userChangeSomeContentOfHtml(someUserContent: string) {
const base64Layout = Base64.encode(dbLayout+ someUserContent);
const layouthPath = this.sanitizer.bypassSecurityTrustResourceUrl("data:text/html;base64," + base64Layout);
this.iframe.nativeElement.contentWindow.location.replace(layoutPath);
}
}
Unfortunately variable layoutPath is base64 and location.replace leads me to nowhere.
How can I solve this location stack bypass with a base64 content?

having issues using face detection API from Clarifai API

I have added the face detection API from Clarifai APi to my project, however, whenever i copy an image to my project and click on detects, it actually shows the image but it is not detecting the face.
see below App.js and FaceRecognition.js
import React, {Component} from 'react';
import Clarifai from 'clarifai';
import Navigation from './components/Navigation/Navigation';
import Logo from './components/Logo/Logo';
import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm';
import FaceRecognition from './components/FaceRecognition/FaceRecognition';
import Rank from './components/Rank/Rank';
import './App.css';
const app = new Clarifai.App({
apiKey: 'xxxxxxxxxxxx'
});
class App extends Component {
constructor() {
super();
this.state = {
input: '',
imageUrl: '',
box: {}
}
}
calculateFaceLocation =(data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return {
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height)
}
}
displayFaceBox = (box) => {
console.log(box)
this.setState({box: box});
}
onInputChange = (event) => {
this.setState({input: event.target.value})
}
onButtonSubmit = () => {
this.setState({imageUrl: this.state.input})
app.models.predict(
Clarifai.FACE_DETECT_MODEL,
this.state.input)
.then( response => this.displayFaceBox(this.calculateFaceLocation(response)))
.catch(err => console.log(err));
}
render() {
return (
<div className="App">
<Navigation />
<Logo />
<Rank />
<ImageLinkForm
onInputChange={this.onInputChange}
onButtonSubmit={this.onButtonSubmit} />
<FaceRecognition box={this.state.box} imageUrl={this.state.imageUrl}/>
</div>
);
}
}
export default App;
FaceRecognition.js
import React from 'react';
import './FaceRecognition.css';
const FaceRecognition = ({imageUrl, box}) => {
return (
<div className='center ma'>
<div className='absolute mt2'>
<img id='inputimage' alt='' src={imageUrl} width='500px' height='auto' />
<div className='bounding-box' style=
{{top: box.topRow, right: box.rightCol, bottom: box.bottomRow, left: box.leftCol}}></div>
</div>
</div>
);
}
export default FaceRecognition;
FaceRecognition.css
bounding-box {
position: absolute;
box-shadow: 0 0 0 3px #149df2 inset;
display: flex;
flex-wrap: wrap;
justify-content: center;
cursor: pointer;
}
what am i doing wrong?
i tried copy paste from the actual Clarifai API code, but no luck
the bounding-box css is not even showing up in the console.
please help me
First of all, please don't use this client: https://github.com/Clarifai/clarifai-javascript, it has been deprecated for a while and several things in this package are very old and broken.
If you're purely developing client-side, you can use the REST endpoints directly: https://docs.clarifai.com/api-guide/predict/images (see "Javascript (REST)" snippets throughout the docs)
I also recommend to use PAT instead of API keys. This will allow you access across all your Clarifai apps with a single token.
Clarifai has changed the way to use their Api. On Clarifai Face detect model , click to use model, then you can copy the code on how to use their Api.
https://clarifai.com/clarifai/main/models/face-detection?utm_source=clarifai&utm_medium=referral&tab=versions
Then you can import your PAT and other credentials requested for in the code from Clarifai portal.
Use this as a guide https://help.clarifai.com/hc/en-us/articles/4408131744407-Integrating-Clarifai-in-your-React-Javascript-project
You are welcome 🤗

Fit content to angular powerBi client iframe

I have a couple of reports designed in power BI. The problem is as follows: The iframe I have created has a height of 80rem (that's fine). The problem is that in the event that the report is of a lower height there is a blank space that I want to remove.
I have been testing with css and if I make it smaller the height of the iframe other reports are cut, if I remove the height the report stays with a size of 300w x 150h, I have also tried reading using pages layout (I don't know how to use it because I don't know where the key is taken from), display option and visual layout. All this without success. The guide I use is the following: https://github.com/Microsoft/PowerBI-JavaScript/wiki/Custom-Layout
reading that I feel that it is solved with pages layout but I don't know how to use it. Do you have a solution? Thanks in advance.
The power bi config is this:
this.config = {
accessToken: accessToken && accessToken.currentValue ? accessToken.currentValue : this.config.accessToken,
tokenType: tokenType && tokenType.currentValue ? this.getTokenType(tokenType.currentValue) : this.config.tokenType,
embedUrl: embedUrl && embedUrl.currentValue ? embedUrl.currentValue : this.config.embedUrl,
type: type && type.currentValue ? type.currentValue : this.config.type,
id: id && id.currentValue ? id.currentValue : this.config.id,
filters: filtersExternal && filtersExternal.currentValue ? filtersExternal.currentValue : this.config.filters,
...this.fixedConfig
};
And Fixed config:
// Fixed configuration
fixedConfig: IEmbedConfiguration = {
settings: {
navContentPaneEnabled: false,
filterPaneEnabled: false,
customLayout: {
pageSize: {
type: models.PageSizeType.Custom,
height: 600,
width: 1300
}
}
}
};
This is working for me to resize the the power bi report in UI
this.reportService.getReportObject(reportName).subscribe(res => {
this.reportmodel = res;
this.config = {
type: res.reportType,
id: res.id,
accessToken: res.embedToken.token,
embedUrl: res.embedUrl,
permissions: pbi.models.Permissions.All,
tokenType: pbi.models.TokenType.Embed,
viewMode: pbi.models.ViewMode.View,
settings: {
filterPaneEnabled: false,
navContentPaneEnabled: navigation,
layoutType: pbi.models.LayoutType.Custom,
customLayout: {
displayOption: pbi.models.DisplayOption.FitToWidth
}
}
};
this.hideloader();
this.pbiContainerElement = document.getElementById('pbi-container');
this.powerBiService = new NgxPowerBiService();
this.powerBiService.reset(this.pbiContainerElement);
const reportobj = this.powerBiService.embed(this.pbiContainerElement, this.config) as pbi.Report;
reportobj.off('loaded');
reportobj.on('loaded', () => {
reportobj.setPage(this.reportmodel.pageName);
});
},
err => {
this.hideloader();
console.log(err);
this.dashboardLoadError = true;
throw new Error('Exception occured while rendering the dashboard:' + err);
});
Good Morning,
Finally I discovered that my problem was that in order to maintain the 16: 9 aspect ratio on certain screens, the height decreased a lot. To solve it was as simple as modifying the height of the container div of the iframe depending on the width of the screen:
#media only screen and (max-width: 1600px) {
// TODO: A variable
height: 60rem;
}
#media only screen and (max-width: 1300px) {
// TODO: A variable
height: 55rem;
}
#media only screen and (max-width: 800px) {
// TODO: A variable
height: 35rem;
}
that way the iframe adjusts to the content of the report.
My HTML div & iframe:
<div class="tn-powerbi__frame" [ngClass]="{ 'tn-powerbi__frame--fullscreen': fullscreen,'tn-powerbi__frame--insurtech': reportId===20 }" #powerbiFrame></div>
Iván Allué

Best way to configure Reactstrap carousel images to be responsive

I have done a lot of looking but there is suprisingly little documentation in regard to reactstrap carousel image responsiveness.
My ReactStrap carousel resizes responsively but the images do not.
Options I have researched/tried:
CSS via className in the carousel component itself? This is the one I thought might be best, but I haven't found a combination of background-size, height, and max-width that resizes the image properly.
srcset ? I'm not sure how to implement this or any other inline attribute, given that the carousel is a component
Perhaps some place in the carousel component itself?
Or is there a better way for me to modify the images?
Or is #media the answer via css?
`
const items = [
{
src: 'img1.png',
altText: '',
caption: ''
},
{
src: 'img2.png',
altText: '',
caption: 'Freedom Isn\'t Free'
},
{
src: 'img3.png',
altText: '',
caption: ''
}
];
class HomeCarousel extends Component {
constructor(props) {
super(props);
this.state = { activeIndex: 0 };
this.next = this.next.bind(this);
this.previous = this.previous.bind(this);
this.goToIndex = this.goToIndex.bind(this);
this.onExiting = this.onExiting.bind(this);
this.onExited = this.onExited.bind(this);
}
onExiting() {
this.animating = true;
}
onExited() {
this.animating = false;
}
next() {
if (this.animating) return;
const nextIndex = this.state.activeIndex === items.length - 1 ? 0 : this.state.activeIndex + 1;
this.setState({ activeIndex: nextIndex });
}
previous() {
if (this.animating) return;
const nextIndex = this.state.activeIndex === 0 ? items.length - 1 : this.state.activeIndex - 1;
this.setState({ activeIndex: nextIndex });
}
goToIndex(newIndex) {
if (this.animating) return;
this.setState({ activeIndex: newIndex });
}
render() {
const { activeIndex } = this.state;
const slides = items.map((item) => {
return (
<CarouselItem
className="carouselImg"
onExiting={this.onExiting}
onExited={this.onExited}
key={item.src}
>
<img src={item.src} alt={item.altText} />
<CarouselCaption captionText={item.caption} captionHeader={item.caption} />
</CarouselItem>
);
});
return (
<Carousel
activeIndex={activeIndex}
next={this.next}
previous={this.previous}
>
<CarouselIndicators items={items} activeIndex={activeIndex} onClickHandler={this.goToIndex} />
{slides}
<CarouselControl direction="prev" directionText="Previous" onClickHandler={this.previous} />
<CarouselControl direction="next" directionText="Next" onClickHandler={this.next} />
</Carousel>
);
}
}
export default HomeCarousel;
`
Good day and Hello,
I already tried this reactstrap with the Carousel component in my reactjs app.
I solved this by adding bootstrap 4 classess "d-block w-100".
I created this in my reactstrap Carousel component and in this element
from this:
<img src={item.src} alt={item.altText} />
I changed to:
<img className="d-block w-100" src={item.src} alt={item.altText} />
I just copied these classes (d-block w-100) from bootstrap 4 documentation
https://getbootstrap.com/docs/4.0/components/carousel/
This is my example that I used Reactstrap Carousel with Dynamic data from my WordPress Rest API data.
https://github.com/jun20/React-JS-and-WP-Rest-API/tree/home-carousel-final
.carousel-item > img {
width: 100%;
}
... will fix your problem.
And it has nothing to do with Reactstrap. That's probably why you didn't find much. Has to do with the TwBs Carousel alone. I personally don't see any reason why that rule is not part of TwBs carousel CSS, because everyone expects that <img> to have a width of 100% of its parent.
If you want to limit it to a particular carousel, modify the selector accordingly.
Another frequently requested TwBs carousel mod is:
.carousel-control-prev,.carousel-control-next {
cursor:pointer;
}
Given bootstrap uses flexbox, you can make the reactstrap carousel images responsive by adding this to your css:
.carousel-item, .carousel-item.active {
align-items:center;
}
This seems to prevent the image height from stretching. Worked for me!
Based on the reactstrap Carousel example 1 on this page https://reactstrap.github.io/components/carousel/
Here's how I got it to be responsive in my use case:
<CarouselItem
onExiting={() => setAnimating(true)}
onExited={() => setAnimating(false)}
key={item.src}
>
<img src={item.src} alt={item.altText} style={{ width: "100%"}}/>
<CarouselCaption captionText={item.caption} captionHeader={item.caption} />
</CarouselItem>
So, passing in style={{ width: "100%"}} to the img tag, made my oversized images fit the screen perfectly and may work for others coming here.

svg styles interfering with each other

I have a bunch of logo's, generated with illustrator, that I would like to embed in my website directly. The svgs all have a <style> element where the styles are defined inside the svg element, something like this:
<svg>
<style>
.st1 { fill:#ff00ff; }
.st2 { fill:#ff3421; }
/* ... and so on */
</style>
<!-- svg paths and shapes -->
</svg>
The problem is that these styles interfer with each other. So if the last images defines .st21 {fill:#555555} this style is applied to all path with class="st21", including paths from all previously loaded svg images.
In another thread somebody suggested to wrap my svg-xml with an <object> tag, that doesn't seem to work.
How can I make sure that inline SVG styles are not interfering with each other, without touching the actual SVG code?
here's a pen to illustrate the problem: https://codepen.io/pwkip/pen/RLPgpW
I would suggest to export svg with appropriate CSS properties in the first place.
During export from Illustrator choose :style attributes it would be something like this in svg:
<path style="fill: red"></path>
It could increase your file size but it definitely do the job. I found a nice explanation here
I came up with a JavaScript solution. Although this might be a little overkill and slow if you use a lot of SVGs. But this works fine so far.
What I do is, I iterate over all SVGs and collect/parse their CSS styles. I collect all class names and properties and apply them manually onto the SVG elements.
const svgCollection = document.querySelectorAll( 'svg' );
function parseStyles( styleTag ) {
if ( !styleTag ) {
return {};
}
const classCollection = {};
const plain = styleTag.innerHTML;
const regex = /\.([^\s{]+)[\s]*\{([\s\S]+?)\}/;
const propertyRegex = /([\w\-]+)[\s]*:[\s]*([^;]+)/;
const result = plain.match( new RegExp( regex, 'g' ) );
if ( result ) {
result.forEach( c => {
const classResult = c.match( regex );
const propertiesResult = classResult[ 2 ].match( new RegExp( propertyRegex, 'g' ) );
const properties = propertiesResult.reduce( ( collection, item ) => {
const p = item.match( propertyRegex );
collection[ p[ 1 ] ] = p[ 2 ];
return collection;
}, {} );
classCollection[ classResult[ 1 ] ] = properties;
} );
return classCollection;
}
return {};
}
function applyProperties( element, properties ) {
if ( !properties ) {
return;
}
Object.keys( properties ).forEach( key => {
element.style[ key ] = properties[ key ];
} );
}
function applyStyles( element, styles ) {
const classNames = ( element.getAttribute( 'class' ) || '' ).split( ' ' );
classNames.forEach( c => {
applyProperties( element, styles[ c ] );
} );
element.setAttribute( 'class', '' );
}
for ( let i = 0; i < svgCollection.length; i += 1 ) {
const svg = svgCollection[ i ];
const styles = parseStyles( svg.querySelector( 'style' ) );
const elements = svg.querySelectorAll( '[class]' );
for ( let j = 0; j < elements.length; j += 1 ) {
applyStyles( elements[ j ], styles );
}
}
<p>this shape should be blue:</p>
<svg height="210" width="210">
<style>
.st1 {
fill:blue;
}
</style>
<polygon points="100,10 40,198 190,78 10,78 160,198" class="st1"/>
</svg>
<p>this shape should be red:</p>
<svg height="210" width="210">
<style>
.st1 {
fill:red;
}
</style>
<ellipse cx="105" cy="80" rx="100" ry="50" class="st1" />
</svg>
Even though this works great, I wouldn't suggest it (as mentioned in the comments at your question). Better to set CSS Properties to Presentation Attributes in Illustrater

Resources