I am trying to use Next.js image component for an image that is absolute.
https://play.tailwindcss.com/BGPOl7QECG
<div class="mt-12 sm:mt-16 lg:mt-0">
<div class="pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-full">
<img class="w-full rounded-xl shadow-xl ring-1 ring-black ring-opacity-5 lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none" src="https://via.placeholder.com/1920x1080.png" alt="Inbox user interface">
</div>
</div>
I tried this
import Image from 'next/image'
....
<div className="mt-12 sm:mt-16 lg:mt-0">
<div className="pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-full">
<div className="w-full rounded-xl shadow-xl ring-1 ring-black ring-opacity-5 lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none">
<div className="relative">
<Image src={image} alt={alt} layout="fill" />
</div>
</div>
</div>
</div>
but the image is not positioned correctly similar to how it is when not using Next.js image component. How should I use the Image so it displays similar to the one without Image?
I think you can just append the string directly into the className like so
<Image className="w-full rounded-xl shadow-xl..." ... />
As we can read in official docs layout="fill" :
When fill, the image will stretch both width and height to the
dimensions of the parent element, provided the parent element is
relative.
This is usually paired with the objectFit property.
Ensure the parent element has position: relative in their stylesheet.
Here You have official example (demo the fill layout) and how it use ;-)
And Your code with my little improvements index.js (home page):
import Head from "next/head";
import Image from "next/image";
export default function Home() {
return (
<div>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="relative bg-white pt-16 pb-32 overflow-hidden">
<div className="relative">
<div className="lg:mx-auto lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-2 lg:grid-flow-col-dense lg:gap-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-16 lg:max-w-none lg:mx-0 lg:px-0">
<div>
<div className="mt-6">
<h2 className="text-3xl font-extrabold tracking-tight text-gray-900">
Title
</h2>
<p className="mt-4 text-lg text-gray-500">
Semper curabitur ullamcorper posuere nunc sed. Ornare
iaculis bibendum malesuada faucibus lacinia porttitor.
Pulvinar laoreet sagittis viverra duis. In venenatis sem
arcu pretium pharetra at. Lectus viverra dui tellus ornare
pharetra.
</p>
</div>
</div>
</div>
<div className="mt-12 sm:mt-16 lg:mt-0">
<div className="pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-full">
<div className="w-full rounded-xl shadow-xl ring-1 ring-black ring-opacity-5 lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none">
<div
className="relative"
style={{ width: "600px", height: "500px" }}
>
<Image
src="https://images.unsplash.com/photo-1636806663015-088d3d1ce2c8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1171&q=80"
layout="fill"
alt="happy new year"
objectPosition="center"
objectFit="cover"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
For these photos to be displayed you need to add this code in next.config.js
module.exports = {
reactStrictMode: true,
images: {
domains: ["images.unsplash.com"],
},
};
Output:
Tested with "tailwindcss": "^3.0.5" "next": "12.0.7", "react": "17.0.2",
Related
I'm building a slider with React and framer motion. My idea is to subtract scrollWidth with offsetWidth to get the remaining width of the element.
I always get the value of zero (somehow they are equal). I printed the object and I saw that scrollWidth value returns clientWidth instead.
In the object the value of scrollWidth is totaly different and I cant tell why.
I am Creating This Same Project Carousel Slider In Next.js
But I got scrollWidth is Undefined
I dont Know What Happend But..
I got scrollWidth is undefined
enter image description here
import React, { useEffect, useRef, useState } from 'react'
import { motion } from 'framer-motion';
import cardsUser from '../pages/CardsUsers'
const CardCaousel = () => {
const [width,setWidth] = useState(0)
const carousel = useRef()
useEffect(()=>{
setWidth(carousel.current.scrollWidth - carousel.current.offsetWidth)
},[])
return (
<div className="container max-w-full bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 p-5 bggradient">
<div className="liveactionscontainer mt-20">
<h1 className='text-center text-white font-extralight text-6xl mt-2 mb-3'>Live Actions </h1>
<p className='font-extralight text-gray-500 text-center'>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Perspiciatis, suscipit repellat
<br/>
inventore dolor quia quos molestias quae vitae? Eveniet nobis, laborum voluptas culpa libero similique.</p>
<div className="myflex flex justify-center" data-aos="fade-right">
<motion.div className="carousel">
<motion.div
drag="X"
dragConstraints={{right:0,left:-width}}
className="inner-carousel"
>
{cardsUser.map((e)=>{
return (
<motion.div className='item' key={e}>
<div className="mycolumn mb-10">
<div class="nft">
<div class='main'>
<img class='tokenImage' src={e.Imgsrc} alt="NFT" />
<h2>{e.name}</h2>
<p class='description'>Lorem, ipsum dolor sit amet consectetur adipisicing elit. </p>
<div class='tokenInfo'>
<div class="price">
<ins>◘</ins>
<p>0.031 ETH</p>
</div>
<div class="duration">
<button>Place bid</button>
</div>
</div>
<hr />
<div class='creator'>
<div class='wrapper'>
<img src={e.profileImg} alt="Creator" />
</div>
<p><ins>Creation of</ins><span className='text-white'> NF</span> </p>
</div>
</div>
</div>
</div>
</motion.div>
);})}
</motion.div>
</motion.div>
</div>
</div>
</div>
)
}
export default CardCaousel
I'm creating a React PWA for a client using Tailwind CSS and I want to achieve a layout in which there's a header fixed to the top of the screen and a navbar fixed to the bottom of the screen. In between I'll display scrollable content of dynamic size.
I've been struggling with this problem for the most part of the day and I'm following the instructions on this answer as well as the code it provided here.
I though I got it, as I implemented all the recommended classes in the relevant components and I got this result on my browser dev tools:
However, I got curious and decided to open the page on my phone. This is the result there and, as you can see, neither of the desired elements are actually fixed to the screen:
At this point I'm completely lost. I've tried using className={fixed} in the Navbar, but it ends up clipping part of the content even when adding margin or padding to either the navbar or the content.
How can I fix both header and navbar to the screen while keeping the content scrollable?
These are the relevant parts of my code:
App.js:
function App() {
return (
<Router>
<div className='flex flex-col h-screen overflow-hidden'>
<Header></Header>
<div className='MainContent flex-1 overflow-y-scroll py-2 mx-2'>
<Routes>
<Route path="/" element={<OrderView />} />
<Route path="/DeliverymenView" element={<DeliverymenView />} />
<Route path="/InventoryView" element={<InventoryView />} />
<Route path="/RouteGenerationView" element={<RouteGenerationView />} />
<Route path="/AdministrativeView" element={<AdministrativeView />} />
<Route path="*" element={<ErrorView />} />
</Routes>
</div>
<Navbar></Navbar>
</div>
</Router>
);
}
Header.js:
const Header = () => {
return (
<div className="Header shadow-md bg-white w-full ">
<CurrentPage />
</div>
)
}
Navbar.js:
function Navbar() {
return (
<div className="Navbar w-full flex flex-row gap-x-2 justify-evenly py-1 bg-white drop-shadow-md-top">
<Link to="/">
<MdShoppingCart className="text-zinc-400 text-5xl "></MdShoppingCart>
</Link>
<Link to="/DeliverymenView">
<MdPerson className="text-zinc-400 text-5xl "></MdPerson>
</Link>
<Link to="/InventoryView">
<MdViewList className="text-zinc-400 text-5xl "></MdViewList>
</Link>
<Link to="/RouteGenerationView">
<MdDeliveryDining className="text-zinc-400 text-5xl "></MdDeliveryDining>
</Link>
</div>
)
}
One way to keep flex on the parent container is to add sticky to the header and footer divs, with top-0 or bottom-0, like this:
Modified code from the tailwind play linked in your question.
<div class="flex flex-col h-screen">
<header class="w-full text-center border-b border-grey p-4 sticky top-0">Some header</header>
<main class="flex-1 overflow-y-scroll">
<div class="min-h-screen bg-slate-100">
<p>This is a very long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-200">
<p>This is second long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-100">
<p>This is third long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-200">
<p>This is fourth long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-100">
<p>This is fifth long section that consumes 100% viewport height!</p>
</div>
</main>
<footer class="w-full text-center border-t border-grey p-4 sticky bottom-0">some footer</footer>
</div>
Actually you don't need to set the position to "fixed" or "absolut". The problem can be solved simpler.
You need 4 divs. One as a container (we can call its class "root") which contains the further 3 divs.
For defining how much space each inner div can take from the root div we can use "flex" (with "flex" you can define the proportion to other components).
(You can of course change height and width of root as you like)
.root {
height: 70vh;
width: 50vw;
display: flex;
flex-direction: column;
justify-content: stretch;
}
.Header--container {
flex: 1;
background-color: green;
}
.Footer--container {
flex: 1;
background-color: red;
}
.Content--container {
flex: 5;
background-color: white;
overflow-y: scroll;
}
<div class="root">
<div class="Header--container">
</div>
<div class="Content--container">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</div>
<div class="Footer--container">
</div>
</div>
I am making a dropdown accordion. After adapting my code to the example bellow, everything works fine:
Example: https://codepen.io/CreativeBulma/pen/YbQqoQ
trainingData
[{
"von": "17:00",
"bis": "18:00",
"tag": "Mittwoch",
"trainingsid": 46
},
{
"von": "19:00",
"bis": "21:00",
"tag": "Donnerstag",
"trainingsid": 51
}]
That's how it works:
<div ref={collapsiblesRef} id={`accordion_first2`}>
<div className="card">
<header className="card-header">
<p className="card-header-title">
montaj
</p>
<a href={`#collapsible-card-0`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-0`} className="is-collapsible" data-parent={`accordion_first2`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
<div className="card">
<header className="card-header">
<p className="card-header-title">
dasdasd
</p>
<a href={`#collapsible-card-1`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-1`} className="is-collapsible" data-parent={`accordion_first2`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
</div>
Since I am having several elements I want to add to the dropdown, I am using a loop. But unfortunately, after adding the loop, the collapsibles aren't working properly - they are staying open and I cannot close them or interact with them.
So that's actually what I want:
<div ref={collapsiblesRef} id={`accordion_first`}>
{trainingData.map((d, i) => (
<div className="card" key={i}>
<header className="card-header">
<p className="card-header-title">
{d.tag}
</p>
<a href={`#collapsible-card-${i}`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-${i}`} className="is-collapsible" data-parent={`accordion_first`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
</div>*/}
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
))}
</div>
I played a bit with the code, this works for me.
import React from "react";
import bulmaCollapsible from '#creativebulma/bulma-collapsible';
import 'bulma';
import '#creativebulma/bulma-collapsible';
///I want to generate a random number of collapsibles.
const array = [0,1,2,3,4,5,6]
class Collapsibles extends React.Component {
componentDidMount() {
this.collapsibles = bulmaCollapsible.attach(".is-collapsible", {
container: this.refs.collapsibles
});
}
render() {
const collapsibles = array.map((c,i) => <article className="message">
<div className="message-header">
<p>
Question 1{" "}
<a href={"#collapsible-message-accordion-"+ i.toString()} data-action="collapse">
Collapse/Expand
</a>
</p>
</div>
<div
id={"collapsible-message-accordion-"+ i.toString()}
className="message-body is-collapsible is-active"
data-parent="accordion_first"
>
<div className="message-body-content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
<strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
Nullam gravida purus diam, et dictum
<a>felis venenatis</a> efficitur. Aenean ac{" "}
<em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
magna a neque. Donec dui urna, vehicula et sem eget, facilisis
sodales sem.
</div>
</div>
</article>)
return (
<div ref="collapsibles" id="accordion_first">
{collapsibles}
</div>
)
}
}
export default Collapsibles
A few notes on the code:
First, I assume you're aware that bulmaCollapsible is an npm package that needs to be installed. You can find directions for installation here.
I didn't fully understand where you got your code from, I copied mine from the CodePen you provided. Each collapsible container is an article tag.
My code lacks any transition properties. So it won't slowly open and close. You'll have to add some minor css to make that happen.
The method attach is responsible to initialise any element with the className of is-collapsible. It was made so you can initialise multiple collapsibles at once.
In my code I created an array const called "array". Then I used the map method like you did to generate multiple collapsibles.
The following will give you 1 collapsible:
<article className="message">
<div className="message-header">
<p>
Question 1{" "}
<a href={"#collapsible-message-accordion-"+ i.toString()} data-action="collapse">
Collapse/Expand
</a>
</p>
</div>
<div
id={"collapsible-message-accordion-"+ i.toString()}
className="message-body is-collapsible is-active"
data-parent="accordion_first"
>
<div className="message-body-content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
<strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
Nullam gravida purus diam, et dictum
<a>felis venenatis</a> efficitur. Aenean ac{" "}
<em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
magna a neque. Donec dui urna, vehicula et sem eget, facilisis
sodales sem.
</div>
</div>
Each collapsible needs to have a unique id. For each collapsible we use an a tag with an href attribute equal to the collapsible's id. This is reflected in the lines where you see href={"#collapsible-message-accordion-"+ i.toString()} and id={"#collapsible-message-accordion-"+ i.toString()}
To know more about how this package work, visit their JS API page.
I got issue when trying to add a "screen" prefix to grid-column, the layout is perfect but when I add md: to grid-col-span-6 everything is messed up.
this is the code :
import React from "react";
import app from "../images/app.png";
const Featured = () => {
return (
<div className="mt-52 ">
<h1 className="text-primary-dark-theme text-5xl mt-14">Projects</h1>
<div className="grid grid-cols-12 grid-rows-1 mt-20 ">
<div className="row-start-1 row-span-1 col-start-1 md:col-span-6">
<img src={app} alt="" className="w-full" />
</div>
<div className="row-start-1 row-span-1 col-start-6 col-span-7">
<div className="h-full w-full">
<h1 className="text-right text-primary-dark-theme">
Featured Project
</h1>
<h1 className="text-right text-gray-300 font-bold ">Title</h1>
<p className="p-5 bg-gray-800 text-gray-400 shadow-lg rounded-md mt-5">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Optio id
doloribus sequi repellendus aperiam dolore!
</p>
</div>
</div>
</div>
</div>
);
};
export default Featured;
This is how the ui looks in md
this is the result i want to have
this what happened when i add md predix to col-span-6
The issue seems to be that when applying the responsive md:col-span-6 it also overrides col-start-1 (you can see the styles no longer applied in the dev tools). Adding md:col-start-1 seems to fix this behaviour.
However, simply changing your image's wrapper <div /> to:
<div class="row-start-1 row-span-1 col-start-1 col-span-12">
Seems to have the desired result.
I am playing around with reactjs and wanted to prompt an apk install, similar to how you would prompt a .zip download, I have:
return (
<div className="card border-0 flex-row flex-wrap p-0 m-0" style={{background:'none'}}>
<div className="col-2 p-0 m-0">
<div className="card-header border-0 m-0 mt-1 p-0">
<img className="imgBorder" src={require('./assets/img/car.jpg')} width={'95.6dp'} height={'119.5dp'} alt=""/>
</div>
</div>
<div className="col-10">
<div className="card-block align-items-center p-0 m-0">
<h4 className="card-title" style={{color:'white', fontWeight: 'bold'}}>{this.props.title}</h4>
<p className="card-text pl-5 mb-0" style={{color:'white', lineHeight:'1'}}>Sed ut perspiciatis unde omnis iste natus error sit...</p>
<p className="muted m-0 p-0" style={{color:'white', lineHeight:'1.4', fontSize:'80%'}}>05/05/20</p>
<SportsEsportsIcon /><Trans i18nKey='library.play'>Play</Trans>
</div>
</div>
<div className="w-100"></div>
</div>
);
and the href={this.props.url} is pointing to a server with a .apk file. However, when I install the app (PWA), instead of prompting for download, I get taken to the url where the file is. Anyway I can trigger the download?
You need to specify the download attribute on the link, versus linking to the location alone.
Attributes
download
Prompts the user to save the linked URL instead of navigating to it.
Can be used with or without a value
<a
href={this.props.url}
className="playBtn my-2"
download
// or download="myAwesomeApp.apk" if you wanted to provide a name hint
>
<SportsEsportsIcon />
<Trans i18nKey='library.play'>
Play
</Trans>
</a>