layout fill property is not applying to the image - nextjs-image

I am working on a next js project and getting an error when i try to apply layout="fill" as it is always underlined red and upon saving it seems the layout fill property is not apply on the image as the size isn't covering the entire page ( or is not big enough ) as i am intending it to
here is the code....
import Image from "next/image";
import React from "react";
// import Button from "./Button";
import product1 from "../public/product1.jpeg";
function Landing() {
return (
<section className="sticky top-0 mx-auto flex h-screen max-w-[1350px] items-center justify-between px-8">
<div className="space-y-8">
<h1 className="space-y-3 text-5xl font-semibold tracking-wide lg:text-6xl xl:text-7xl">
<span className="block bg-gradient-to-r from-pink-500 to-violet-500 bg-clip-text text-transparent">
iPad
</span>
<span className="block">Lovable. Drawable. Magical</span>
</h1>
<div className="space-x-8">
{/* <Button title="Buy Now" /> */}
<a className="link">Learn More</a>
</div>
</div>
<div className="relative hidden h-[450px] w-[450px] transition-all duration-500 md:inline lg:h-[650px] lg:w-[600px]">
<Image src={product1} layout="fill" objectFit="contain" alt="" />
</div>
</section>
);
}
export default Landing;
when hover over layout it shows an error
Type '{ src: StaticImageData; layout: string; objectFit: string; alt: string; }' is not assignable to type 'IntrinsicAttributes & Omit<DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "ref" | ... 5 more ... | "loading"> & { ...; }'.
Property 'layout' does not exist on type 'IntrinsicAttributes & Omit<DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "ref" | ... 5 more ... | "loading"> & { ...; }'.ts(2322)
if i use the image as
src="/public/product1.jpeg" i get a different error src image is missing the width property which shouldn't be if layout-fill is mentioned
am new to web development so i get lost in small errors :D
i have tried to google around and find a fix but am confused as to why it is asking to mention width and height if layout fill property is being used
would appreciate the help and explanation
thnx..

Related

Need help getting local image to appear using Framer Motion and NEXTjs

I am using NEXTJS and framer motion but the local image is not appearing on the web page. Instead I get that little clip art thing.Below is my code to the particular component not working:
import React from 'react'
import {motion} from "framer-motion";
import aboutPic from './images/wed.jpg'
type Props = {}
function About({}: Props) {
return (
<div className=" flex flex-col relative h-screen text-center md:text-left md:flex-row max-
7xl px-10 justify-evenly mx-auto items-center">
<h3 className="absolute top-24 uppercase tracking-[20px] text-gray-500 text-2xl">
About
</h3>
<motion.img
initial={{
x:-200,
}}
transition={{
duration:1.2,
}}
whileInView={{x: 0}}
src={aboutPic}
/>
</div>
)
}
export default About
Most probably due to the location of your image.
According to your specified path, your image should be in the same folder as your 'About' component. Check your image location and path.
Note that in default image imports you can't use direct path for images stored in public folder as in urls.
Instead, you have to locate it like any exported component.
If you are in 'pages' folder and the 'images' folder is in 'public' for example:
import aboutPic from '../public/images/wed.jpg'
or
<img src='/images/wed.jpg'/>

Problem finding string atached to json file when translating (i18n)

I have successfully translated many of the pages on my website project but now I have moved to translate specific components that were created and it is not working.
The error message I get is as follows: "TypeError: Cannot read properties of undefined (reading 'titulo')"
**Note: I am using NextJS and TailwindCSS
This is the code for the JSON file strings where it should grab the translation, I have two files, one for ES (Spanish) and another EN (English)
"heroBanner":{
"titulo": "Ayudamos a PYMES a Captar la Atención mediante Publicidad Digital",
"subtitulo": "BIENVENIDO A COTTONMEDIA"
},
This is the component code where I have passed the props:
import React from 'react'
import Custom__Cursor from './Custom__Cursor'
function Hero__Banner(props) {
return (
<div>
<div className="relative h-screen">
<div className="h-full w-full">
<video autoPlay muted loop className="object-cover h-screen w-full ">
<source src="/AdsBgVideo.mp4" type="video/mp4">
</source>
</video>
</div>
<div className="absolute top-0 h-full w-full bg-black opacity-60 z-10"></div>
<div className="absolute top-1/4 z-20 max-w-screen-md md:max-w-screen-xl">
<div className='flex flex-col px-10 space-y-5'>
<p className='text-left text-sm md:text-base font-medium tracking-wide filter drop-shadow-md'>{props.titulo}</p>
<p className='text-left text-4xl md:text-5xl leading-normal md:leading-relaxed filter drop-shadow-md'>{props.subtitulo}</p>
</div>
</div>
</div>
</div>
)
}
export default Hero__Banner
Then where the component is rendered I have included these props with the string in order to get the translation as follows:
import Head from 'next/head'
import Image from 'next/image'
import Hero__Banner from '../components/Hero__Banner'
import ScrollToTop from '../components/ScrollToTop'
export default function Home(props) {
const { index, heroBanner } = props;
return (
<div>
<Head>
<title></title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/short-logo.svg" />
</Head>
{/*Main content */}
{/* Hero section */}
<Hero__Banner
titulo={heroBanner.titulo}
subtitulo={heroBanner.subtitulo}
/>
</div>
)
}
export async function getStaticProps({locale}) {
const response = await import(`../lang/${locale}.json`);
return {
props: {
index: response.default.index,
heroBanner: response.default.heroBanner
},
};
}
Even after doing that, I still get the same error, not sure why this is happening. The component translations are now on the index page which is in "pages", so it should work in my opinion. As you can see in the code, I already have some translated sections in the index, which work perfectly.
Error image
Any suggestions?
When you are translating with i18n, and get this error, it could be because you have altered the translation JSON file and the server needs to be restarted. That was the case for me, hope this helps.

React and Tailwind CSS: dynamically generated classes are not being applied

I'm just learning React and Tailwind CSS and had a strange experience with CSS grid using Tailwind classes. I've made the buttons for a calculator, with the last Button spanning two columns:
App.js:
export default function App() {
return (
<div className="flex min-h-screen items-center justify-center bg-blue-400">
<Calculator />
</div>
);
}
Calculator.js
import { IoBackspaceOutline } from "react-icons/io5";
export const Calculator = () => {
return (
<div className="grid grid-cols-4 grid-rows-5 gap-2">
<Button>AC</Button>
<Button>
<IoBackspaceOutline size={26} />
</Button>
<Button>%</Button>
<Button>÷</Button>
<Button>7</Button>
<Button>8</Button>
<Button>9</Button>
<Button>x</Button>
<Button>4</Button>
<Button>5</Button>
<Button>6</Button>
<Button>-</Button>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<Button>+</Button>
<Button>0</Button>
<Button>.</Button>
<Button colSpan={2}>=</Button>
</div>
);
};
const Button = ({ colSpan = 1, rowSpan = 1, children }) => {
return (
<div
className={`col-span-${colSpan} row-span-${rowSpan} bg-white p-3 rounded`}
>
<div className="flex items-center justify-center">{children}</div>
</div>
);
};
This doesn't work (tested in Chrome):
Now here comes the weird part. I replaced the returned JSX from the App component with HTML from a Tailwind tutorial and deleted it again.
<div className="bg-blue-400 text-blue-400 min-h-screen flex items-center justify-center">
<div className="grid grid-cols-3 gap-2">
<div className="col-span-2 bg-white p-10 rounded">1</div>
<div className="bg-white p-10 rounded">2</div>
<div className="row-span-3 bg-white p-10 rounded">3</div>
<div className="bg-white p-10 rounded">4</div>
<div className="bg-white p-10 rounded">5</div>
<div className="bg-white p-10 rounded">6</div>
<div className="col-span-2 bg-white p-10 rounded">7</div>
<div className="bg-white p-10 rounded">8</div>
<div className="bg-white p-10 rounded">9</div>
</div>
</div>
After I Ctrl-Z'd a bunch of times, so I had only the previous code, my button suddenly spans two columns as intended:
I checked to make sure that there were no changes in the code:
My friend even cloned my repo, followed the same steps and got the same result.
He suspects that it has something to do with the variable classNames in my Button component with regards to Tailwind's JIT compiler, but none of us can pinpoint the error.
Am I using variable CSS classes wrong?
This has been a WTF moment. What could be the reason for this?
The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. col-span-${colSpan}) will not be included.
If you only need to span 2 columns, you could pass boolean values which will trigger the addition of a full col-span-2 or row-span-2 utility class to be added:
const Button = ({ colSpan = false, rowSpan = false, children }) => {
return (
<div
className={`${colSpan ? 'col-span-2' : ''} ${rowSpan ? 'row-span-2' : ''} bg-white p-3 rounded`}
>
<div className="flex items-center justify-center">{children}</div>
</div>
);
};
Otherwise, you could pass the values as classes to the Button component:
<Button className='col-span-2 row-span-1'>=</Button>
const Button = ({ className, children }) => {
return (
<div
className={`${className} bg-white p-3 rounded`}
>
<div className="flex items-center justify-center">{children}</div>
</div>
);
};
More information: https://tailwindcss.com/docs/content-configuration#dynamic-class-names
Another tricky solution that worked for me is to use variable with forced type of the possible className values (in typescript) like :
export type TTextSizeClass =
'text-xl' |
'text-2xl' |
'text-3xl' |
'text-4xl' |
'text-5xl' |
'text-6xl' |
'text-7xl' |
'text-8xl' |
'text-9xl'
;
...
const type : number = 6 ;
const textSizeClass : TTextSizeClass = type != 1 ? `text-${type}xl` : 'text-xl';
...
<div className={`font-semibold ${textSizeClass} ${className}`}>text</div>
As Ed Lucas said:
The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. col-span-${colSpan}) will not be included
But now could use safeListing
and
tailwind-safelist-generator package to "pregenerate" our dynamics styles.
With tailwind-safelist-generator, you can generate a safelist.txt file for your theme based on a set of patterns.
Tailwind's JIT mode scans your codebase for class names, and generates
CSS based on what it finds. If a class name is not listed explicitly,
like text-${error ? 'red' : 'green'}-500, Tailwind won't discover it.
To ensure these utilities are generated, you can maintain a file that
lists them explicitly, like a safelist.txt file in the root of your
project.

tailwind css flex-col-reverse not working

I am currently working on a component's responsive styling wherein on large screens I have the div with the text element sitting on top of the div containing the img element and on smaller and medium screens have the div with the image aligned right below the div with the text element. I am using Next.js and and Tailwind CSS for styling.
The styling works fine on large screens but for some reason the div with the text element is not showing in small screens when I already have flex flex-col-reverse in the parent element
Here is how the entire code look like:
import React from 'react'
import Image from 'next/image'
import catImage from '../assets/catImage.webp'
const LargeCard = () => {
return (
<article className='relative flex flex-col-reverse h-screen py-16 lg:h-96' >
<div>
<Image src={catImage}
layout='fill'
objectFit='cover'
className='rounded-2xl'
/>
</div>
<div className='h-96 lg:absolute lg:top-32 lg:left-12' >
<h2 className='text-white text-4xl font-semibold mb-3 w-64' >Cat Ipsum</h2>
<p className='text-lg lg:w-[300px] text-white' >Stretch out on bed i heard this rumor where the humans are our owners, pfft, what do they know?!</p>
<button className='bg-gray-100 text-gray-900 px-4 py-2 rounded-lg mt-5 max-w-md ' >Learn more</button>
</div>
</article>
)
}
export default LargeCard
tailwind.config.js:
module.exports = {
mode: 'jit',
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
maxWidth: {
md: '90vw'
}
},
variants: {
extend: {},
},
plugins: [
require('tailwind-scrollbar-hide')
],
}
forgot to post the answer. I actually solved the following day.
First. flex-col-reverse is actually working.
Second. setting nextjs's <Image> component's objectFit property to cover will set the img element to cover the entire area of it's grandparent element so to contain it you add position relative to the parent div containing it and make sure to define it's height too.
something like this:
<div className='relative h-96'>
<Image src={catImage}
layout='fill'
objectFit='cover'
className='rounded-2xl'
/>
</div>

How to make the text on React Bootstrap 4 Carousel stay, while the images move?

Basically this is the same question as this one, but for the React Bootstrap Carousel component.
So I have a working carousel but I want a text to be on top of it, that doesn't move while the images change.
This is my working Carousel code snippet - as you can see I added my overlay text at the bottom of the loop. It does stay on top, just like I want, but it also adds an additional empty carousel item, which I don't want. (I tried making this work in js-fiddle and codesandbox.io but I'm not smart enough...)
import React from "react";
import Carousel from "react-bootstrap/Carousel";
import "./styles.css";
export default function App() {
let carouselImgs = [
{
title: "Test1",
img: "https://images.app.goo.gl/FrGs95rzsNfc6YkW8"
},
{
title: "Test2",
img: "https://images.app.goo.gl/tPkFSMH796PmV3pq9"
}
];
return (
<Carousel className="App" interval={3000}>
{carouselImgs.map(carouselImg => (
<Carousel.Item
key={carouselImg.title}
className="oneness-container mb-2"
>
<img src={carouselImg.img} className="img-fluid rounded-lg" alt="" />
<Carousel.Caption>
<div className="bottom-center">
<h3 className="rounded px-2 py-1 d-inline">
{carouselImg.title}
</h3>
</div>
</Carousel.Caption>
</Carousel.Item>
))}
{<h1 className="overlay">Overlay title</h1>}
</Carousel>
);
}
CSS of .overlay:
.overlay {
position: absolute;
top: 0;
width: 100%;
}
I like the comment on that answer - that says to this:
<div id="carousel" class="carousel slide">
<!-- Wrapper for slides -->
<div class="carousel-inner" >
<!-- items -->
</div>
</div>
...place [the overlay div] inside the carousel-inner, but still in a div separate from your "item" divs...
But unfortunately I don't know how to get inside the carousel-inner since the React Bootstrap component doesn't show it like that.

Resources