Fitting a large image to a specific size - css

I have a series of images of different size (call it set A) that I am arranging next to each other. Upon press of a button, those images get replaced by a much larger image in original size. I'd like to make sure the replaced image adheres to the original image size. I've tried to apply various container width tricks, but so far have failed.
I've set up a runnable demo here https://stackblitz.com/edit/ionic-au2pcv (code is in home.html and home.ts in pages directory)
If you press the "Switch" button, the images get replaced, as does the size (which I want to avoid)
(please excuse inline CSS styling)
The code:
My template
<ion-content padding>
<div *ngFor="let image of images">
<!-- the reason for this div is to force the placeholder image to this size -->
<!-- doesn't seem to work... -->
<div [ngStyle]="{'width':image.w, 'height':image.h, 'float':left}">
<img [src]="showImage?image.src:placeholder" style="float:left;max-width:100%; max-height:100%;width:auto;height:auto;" />
</div>
</div>
<div style="clear:both">
<button ion-button (click)="toggleImage()">switch</button>
</div>
</ion-content>
The TS:
import { NgStyle } from '#angular/common';
images = [{
src: 'http://lorempixel.com/300/200/',
w:300,
h:200,
},
{
src: 'http://lorempixel.com/100/100/',
w:100,
h:100,
},
{
src: 'http://lorempixel.com/200/80/',
w:200,
h:80,
}];
placeholder = "http://via.placeholder.com/1000x1000";
showImage:boolean = true;
toggleImage() {
this.showImage = !this.showImage;
}

Your demo doesn't show images. Anyways, to acheive this, you don't have to use containers and all other things. It can be acheive by using simple css. Before doing this, make sure to fix the size of the image. for example if you want the 1 image size to be 30% and height 100% and then set object-fit property of the css to be cover. Below is the quick example:-
.image{
width:30%;
height:100%;
object-fit:cover;
}
<img src="../image_path" class="image"/>
Thanks

Related

Non-overlapping, non-cropping, repeating background in CSS

After reading the docs
https://tailwindcss.com/docs/background-repeat
and changing config.tailwind.js to:
theme: {
...
extend: {
...
backgroundImage: {
"footer-sierpinski": "url('/bg-default.svg'), url('/bg-inverted.svg')",
"footer-sierpinski-default": "url('/bg-default.svg')",
"footer-sierpinski-inverted": "url('/bg-inverted.svg')",
},
then in a component using:
<div class="h-32 bg-repeat-round bg-footer-sierpinski">
produces:
How can the config file be changed so that the images are position to the left and to the right, respectively?
Variations tried:
<div class="grid grid-cols-2">
<div class="h-32 bg-repeat-round bg-footer-sierpinski-default"></div>
<div class="h-32 bg-repeat-round bg-footer-sierpinski-inverted"></div>
</div>
this fills the entire footer with triangles but they are not alternating which makes sense since each div has one background image and each is in its own column.
<div class="h-32 bg-repeat-round bg-[url('/bg-default.svg'),_url('/bg-inverted.svg')] bg-[left,_right]"></div>
same as first (bg-[left,_right] is ignored).
Other variation tried; add both triangles inside the background but this produces ugly spacing and overlapping images on different displays.
Sandbox here:
https://codesandbox.io/s/svg-background-image-x0-forked-c7u4t1?file=/style.css:122-127

Sign In With Google button responsive design

Is there any way to make the new "Sign In With Google" button responsive? Specifically, vary the width based on the width of the containing element? I'd really just like to set the width to 100%.
I'm aware I can set the data-width attribute but this sets it to an explicit width and doesn't update if you change it after the initial script load - you have to reload the whole script to resize the width.
This isn't a perfect solution but it works for us. We're using Twitter Bootstrap.
The new JavaScript library has a renderButton method. You can therefore render the button multiple times on one page passing different widths to each button using something like this (400 is the max width allowed by the library)
private renderAllGoogleSignInButtons(): void {
this.renderGoogleSignInButton(document.getElementById('google-signin-xs'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-sm'), 280);
this.renderGoogleSignInButton(document.getElementById('google-signin-md'), 372);
this.renderGoogleSignInButton(document.getElementById('google-signin-lg'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-xl'), 400);
}
private renderGoogleSignInButton(element: HTMLElement, width: number){
const options {
type: 'standard',
....
width: width
};
google.accounts.id.renderButton(element, options);
}
We then use the display classes from bootstrap to hide/show each button depending on the size.
<div class="mx-auto" style="max-width: 400px">
<div class="d-none-sm d-none-md d-none-lg d-none-xl">
<div id="google-signin-xs"></div>
</div>
<div class="d-none d-none-md d-none-lg d-none-xl">
<div id="google-signin-sm"></div>
</div>
<div class="d-none d-none-sm d-none-lg d-none-xl">
<div id="google-signin-md"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-xl">
<div id="google-signin-lg"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-lg">
<div id="google-signin-xl"></div>
</div>
</div>
We use a wrapper container with mx-auto and a max-width to center the buttons but you don't have to do this.
Our actual implementation is slightly different than the above as we're using Angular and the button is a component but you can get the idea from the above.
The only drawback with this method is that the "personalized button" doesn't seem to display for all rendered buttons but it doesn't seem to affect their functionality.
This answer is based on the new Google Identity Services.
You could try listening for a resize in the window using the resize event, then re-render the Google Sign In button on change. The assumption here is that the container will respond to match the window size:
addEventListener('resize', (event) => {});
onresize = (event) => {
const element = document.getElementById('someContainer');
if (element) {
renderGoogleButton(document.getElementById('googleButton'), element.offsetWidth); // adjust to whatever proportion of the "container" you like
}
}
renderGoogleButton(element, width) {
const options = {
type: 'outline',
width: width
}
google.accounts.id.renderButton(element, options);
}
I've also had better results when the button is centered, not left aligned. The following in Bootstrap:
<div class="d-flex justify-content-center">
<div id="googleButton"></div>
</div>
NB: The max width for the Google button as of the time of writing is 400px, so bear that value in mind as the limit.
I did a workaround, and it worked for me. As I needed the button to have 100% width in mobile devices.
If you have another element on the screen that behaves the same way you need (like having its width 100%), you can select it using a querySelector, and get its width element.clientWidth, after this you can pass the width to the renderButton function provided by google.
But this solution is not valid if you would like the button to change its size on resizing.
I used transform: scale like this in the CSS:
.sign_in_btn_wrapper {
transform: scale(1.5, 1.5);
float: left;
margin-left: 20vmin;
font-weight: bold;
}
Then, instead of wrapping it as I intended, I found that it was fine to just add the class directly to the goog div:
<div class="g_id_signin sign_in_btn_wrapper"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left"
data-width="250">
</div>
By fiddling with combinations of data-size and data-width, along with the scaling factors, I was able to make it the size I wanted. You can use CSS media queries to adjust the 'transform: scale' values so that it is 'Responsive' to the display size of the user's device. You could also use other trickier methods by having JS tweak variables in your CSS that are then used to set the scaling factors.
Good luck. You'd think it'd be in the interest of these big 'sign in with' providers to get together a coordinating working group to make it easier for web site developers to make all the sign-in buttons the same damn size -- you know they'd rather not have their button come out smaller, and pages look better when things are uniform. And what's with only having dimensions in pixels? At least give us vw, vh, and my favorite: vmin. (Using vmin to set things like font size means you can often skip more tedious RWD contortions and call it good enough.) </end_rant>

Center spinner in viewport on bootstrap overlay

I'm using the bootstrap-vue overlay on a page that has long content scrolled via the browser window.
<b-overlay :show="loading">
The overlay correctly covers all of the content, even the part below the viewport, but the overlay's built-in spinner is centered on the content rather than the viewport, so the spinner ends up near or below the bottom of the viewport when the content is long enough.
I've tried custom content via a slot, like this...
<b-overlay :show="loading">
<template v-slot:overlay>
<div style="???" class="text-center">
<p style="???">Make me a spinner and center me on the viewport</p>
<b-button
</div>
</template>
...with dozens of ideas for style="???", including position:absolute with different tops, including top=50vh, including !important strewn around, etc., but the content doesn't budge.
// Note that this snippet doesn't run, because I don't see a way to get
// bootstrap-vue via CDN
var app = new Vue({
el: '#app',
data: function() {
return {
message: 'Hello Vue!',
messages: []
}
},
mounted() {
for (let i=0; i<50; i++)
this.messages.push(i)
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<b-overlay :show="true">
{{ message }}
<!-- long content below extends the overlay size -->
<!-- this moves the spinner down and off the viewport -->
<ul>
<li v-for="m in messages" :key="m">{{m}}</li>
</ul>
</b-overlay>
</div>
I think key to solving this is finding the CSS selector that allows me to change the spinner's position to "fixed" as opposed to "absolute" which seems to be what bootstrap generates.
To get spinner on center of screen you need to make it as direct child of body.
If it is nested it will have restrict area inside immediate parents area.
Try to add that separately or once your DOM ready detach overlay and append to body tag.
I ran into the same issue. Adding this line of CSS on the component resolved it for me:
<style>
.position-absolute {
position: fixed !important;
}
</style>
Note: make sure to not include the scoped keyword in your <style> tag, as this will not work for Bootstrap classes.

Prevent Bootstrap from preloading all the hidden-* images

I'm running Twitter Bootstrap 3.2.
My page has a banner image for every breakpoint. That means code like this:
<img class="visible-xs img-responsive" src="headline-768px.jpg"> (128kb)
<img class="visible-sm img-responsive" src="headline-992px.jpg"> (144kb)
<img class="visible-md img-responsive" src="headline-1200px.jpg"> (264kb)
<img class="visible-lg img-responsive" src="headline-2000px.jpg"> (380kb)
The main purpose of having 4 different images is so that mobile devices don't need to download the larger versions. But Bootstrap preloads all the versions regardless of screen size, even if they're hidden at the current breakpoint. This amounts to hundreds of unnecessary kb for every viewer.
Is there a way around this?
Demo of the Problem:
Not all browsers react the same, but typically browser's will load content from a src attribute, regardless of whether some other CSS rule renders that element as invisible.
Here's a baseline example:
<img class="visible-xs img-responsive" src="http://placehold.it/768x150" />
<img class="visible-sm img-responsive" src="http://placehold.it/992x150" />
<img class="visible-md img-responsive" src="http://placehold.it/1200x150"/>
<img class="visible-lg img-responsive" src="http://placehold.it/2000x150"/>
Demo in jsFiddle
Whenever I refresh the page, the browser loads all images, even ones that are initially invisible:
Background Image + Media Queries
This tutorial on Simple Responsive Images With CSS Background Images goes into more depth, but the basic solution works like this:
Create a simple div:
<div class="responsiveBackgroundImage" id="myImage" ></div>
And then sub in the correct background image depending on the screen size:
We'll probably want all the background images to share a couple basic properties like this:
.responsiveBackgroundImage {
width:100%;
background-size: 100%;
background-position: 50% 0%;
background-repeat: no-repeat;
}
Then replace the background-image property for this particular element at each resolution:
#myImage {background-image: url(http://placehold.it/768x150); }
#media (min-width: 768px) { #myImage { background-image: url(http://placehold.it/992x150); }}
#media (min-width: 992px) { #myImage { background-image: url(http://placehold.it/1200x150);}}
#media (min-width: 1200px) { #myImage { background-image: url(http://placehold.it/2000x150);}}
Demo in jsFiddle
Replacing Images with Javascript
Due to limitations with using background images, you might decide to use a real img element and then just dynamically load the images. Rather than loading the element itself, you can do something similar to what angular does with ng-src when evaluating an expression that resolves to a url. When the browser loads each element, it wouldn't be able to find the file location of src="{{personImageUrl}}". Instead, Angular saves the intended url as a data attribute and then loads when appropriate.
First, take each of your images and prefix the src attribute with data-. Now the browser won't automatically start implementing anything, but we still have the information to work with.
<img class="visible-xs img-responsive" data-src="http://placehold.it/768x150"/>
Then query for all the dynamic images we'll eventually want to load.
$dynamicImages = $("[data-src]");
Next, we're going to want to capture window resize events, and on the very first page load, we'll trigger one just so we can make use of the same code. Use a function like this:
$(window).resize(function() {
// Code Goes Here
}).resize();
Then check if each dynamic image is visible. If so, load the image from the data attribute and remove it from the array so we don't have to keep checking and loading it.
$dynamicImages.each(function(index) {
if ($(this).css('display') !== 'none') {
this.src = $(this).data('src');
$dynamicImages.splice(index, 1)
}
});
Demo in jsFiddle
it is not bootstrap, but the browser. You should use background images (instead of <img> tags) together with media queries.
A proper browser will load only the css background image matching the media query, but it makes sense for it to load all images in the markup regardless of their css styling
(Necessary pain until <picture> will be widely supported)
I did it with jQuery in the end.
HTML:
<div id="billboard">
</div>
Javascript:
$(document).ready(function(){
var viewportWidth = $(window).width();
var adaptiveBillboard = function($showTheRightSizeBilboard){
if(viewportWidth<641){
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/ISYNyCw.png">');
}else if(viewportWidth<721){
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/OQeEwOq.png">');
}else if(viewportWidth<769){
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/3WqOdgo.png">');
}else if(viewportWidth<993){
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/KpNKYLq.png">');
}else if(viewportWidth<1201){
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/F00kkbv.png">');
}else{
$('#billboard a').html('<img class="img-responsive" src="http//i.imgur.com/FK5ZMoo.png">');
};
};
//try things once on pageload
$(adaptiveBillboard);
//try things again on every viewport resize
$(window).resize(function(){
viewportWidth = $(window).width();
setTimeout(adaptiveBillboard,100);
});
});
I have used (in combination with bootstrap hidden-xs):
$dynamicLoadImages = $("img.hidden-xs[data-src]");
$(window).resize(function(index) {
for (var i = 0; i < $dynamicLoadImages.length; i++) {
el = $dynamicLoadImages[i];
if ($(el).css('display') !== 'none') {
el.src = $(el).data('src');
$dynamicLoadImages.splice(i, 1);
i--;
}
};
}).resize();
The current top solution works only for every odd element because of the splice method modifying the underlying object and then skipping the next element.

CSS overflow content when container < window height

On this link I've build a simple html/css based layout. What I want to achieve the following: I want that the content section gets a overflow-y as soon the window height is smaller then the content height. The footer and header need to stay in the same position. Only the content section must be smaller.
This sounds very simple, but to my own surprise I couldn't find a solution yet. I'll tried to add some max-/min-height and overflow values to the content section, but this wouldn't work.
Would be awesome if someone could help me out. Thanks
I would use a combination of CSS and jQuery addClass() as follows (I am calling the content section #Content, let's say 600px for this post):
//css
#Content {
height:600px;
//etc.
}
.contentoverflow {
overflow-y:scroll;
}
Now on page load, add an onload function to the body (note that the Content div lacks any classes):
<body onload="checkHeight()">
<div id="Content">
<!--Your content goes here-->
</div>
Now the JavaScript / jQuery:
function checkHeight() {
var scr = screen.availHeight;
var contentHeight = 600; //or whatever number you choose)
if (contentHeight > scr) {
$("#Content").addClass("contentoverflow");
}
}

Resources