Tailwind: Split layout with a video component? - css

I'm trying to build this split layout with Tailwind and React:
But after countless attempts, I only managed to achieve this layout. Using the exact same styling with an image instead of a video works, but I'm unaible to scale / stretch the video container.
I'm under the assumption that this might be related to the width and height properties of the ReactPlayer component, but every attempt to set these at different percentages in order to improve the layout failed.
<div className="bg-green w-full md:w-1/2 order-first lg:order-last md:order-last">
<ReactPlayer
url= {TennisVideo}
className="object-contain h-screen md:h-screen lg:h-screen xl:h-screen w-full "
width='100%'
height='100%'
playing={true}
muted={true}
loop={true}
config={{ youtube: { playerVars: { disablekb: 1 } } }}>
</ReactPlayer>
</div>
Can anyone point me in the right direction?
https://codesandbox.io/s/sharp-hugle-vpuvr?file=/src/App.js

I would imagine that object-contain is a culprit, and should instead be object-cover. More info in the docs here

Related

Next image dynamic size and aspect ratio

I'm creating a blog page using next.js with one main image for each post. The image is of unknown dimensions and an unknown aspect ratio (as each post has a different image). How can I make the image maintain its own aspect ratio and just scale on smaller screens without specifying a fixed height?
I'm forced to use fill with a fixed height container, but that just distorts the image due to the fixed height. The first image below is next/image with fixed height, and the one below it is a plain img tag. How can I get next image to behave like the img tag with dynamic images?
I want each image to maintain its initial aspect ratio, but not lock all images to the same aspect ratio. Is it even possible as it will break next.js rule on layout shift?
Code for next image:
<div className="container relative imageContainer rounded-lg mb-4 overflow-hidden max-w-7xl">
<Image
src={props.post.imageUrl}
alt={props.post.title}
layout="fill"
/>
</div>
imageContainer CSS:
.imageContainer {
height: 30rem;
}
Code for img tag:
<img
className="rounded-lg mb-4 "
src={props.post.imageUrl}
alt={props.post.title}
></img>
One of the main goals of next/image is performance-related, which as you mentioned, involves the elimination of CLS entirely by always requiring some dimensions.
You have a couple of options here.
Option 1 - Use local images
If you are storing all of your blog images with the source code in some sort of /assets folder, you can import them and use them like so and they will not require width or height and will assume their original dimensions (source docs)
import localImage from './assets/some-local-image.png'
function ExampleComponent() {
return (
<Image
src={localImage}
alt="local image"
/>
)
}
Option 2 - Use getStaticProps + probe-image-size
I'm assuming you're reusing a single, generic <Post /> component or something similar, so if you wanted to dynamically grab widths and heights from a list, you could retrieve that info server-side in getStaticProps and pass as props to the component. This comes with a slight performance hit on your server, but assuming you're not regenerating these images often, it shouldn't be a huge problem.
import probe from 'probe-image-size'
function ExampleComponent(props) {
return (
<Image
src={props.img.src}
width={props.img.width}
height={props.img.height}
alt={props.img.alt}
/>
)
}
export async function getStaticProps() {
// Probably will come from a route param, etc.
const imgPath = '/public/some-path.png'
const img = fs.createReadStream(path.join(process.cwd(), imgPath))
// Read img dimensions
const probedImg = await probe(img)
return {
props: {
img: {
width: probedImg.width,
height: probedImg.height,
src: imgPath,
alt: 'some dynamic alt attribute'
}
}
}
}
Option 3 - use an image CDN
Most image CDNs will give you the ability to transform images on the fly and will provide all of these properties for you. You can set them up with a custom Next.js loader.
Option 4 - use the regular <img /> HTML tag
If none of the above solutions work, it's likely that image optimization isn't your #1 concern, and therefore, using the native image tag works totally fine and shouldn't cause any conflicts with other Next.js <Image /> elements on your page.

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>

Set radius just in large screens with tailwind css

I want to make an image have border radius only when the screen is large, otherwise I want it to have straight edges, how can I do that?
I am using Nextjs and Tailwind CSS
You just need to add the lg: or xl: prefix on whatever class you want to conditionally apply according to screen size, take a look at the docs
Here's an example code:
pages/index.js
export default function Home() {
return (
<div className="h-full w-full grid place-items-center">
<div className="w-32 h-32 bg-red-500 lg:rounded-xl"></div>
</div>
);
}
You can check the sandbox

Tooltip on absolute element in React JS

I am using this library https://tvkhoa.github.io/testlib/ to make some nice tooltip in my React App.
I use that code in my own component which look like this
const Tooltip = ({className, children, text, placement = 'bottom', isDisabled = false}) => {
return (
<ReactTippyTooltip className={className} html={<span>{text}</span>}
theme="dark" position={placement} arrow={true} arrowSize="regular"
animation="shift" hideDelay={300}>
{children}
</ReactTippyTooltip>
);
};
On basic elements such as simple images or buttons, everything works fine. But in some cases, I need to have a tooltip on an absolute element. For example on an InfoButton which overlaps an image.
<div className="relative"> <!-- container -->
<img />
<Tooltip> <!-- tooltip container -->
<InfoButton className="absolute top-0 left-0">
</Tooltip>
</div>
But I noticed that the tooltip appears bellow the image, instead of bellow the InfoButton.
If I have a look with the devtool, I can see that my InfoButton is inside a div that represents ReactTippyTooltip, and that div is 0*0 and is positionned bellow the image in the DOM. This is because only its content (InfoButton) is absolute and positionned inside the image. It can be summarized by the following image
I put a className to ReactTippyTooltip as a workaround and I made it absolute as well. Like this my tooltip is at the right place, but I feel like there is something wrong with what I am my doing.
Has anyone encountered some issues with tooltip on absolute elements ?
Can I do some better code with the library I am using ?
Does it exist some react tooltip library that use reference of the element to display the tooltip ?

Fitting a large image to a specific size

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

Resources