Вот следующие варианты поведения, которых я хочу достичь:
1. Сохраняйте исходное соотношение сторон изображения 16/9, пока имеется достаточная ширина экрана; при уменьшении размера экрана (из-за изменения размера или использования небольших устройств) обрезайте изображение, не деформируя его; наконец, на смартфонах обрежьте его до соотношения сторон 1/1 (или 3:4, для iPad в книжной ориентации или для DVD/книги 5:3), не деформируя и не деформируя его.
1.1. Создайте градиент, накладывающийся на изображение, который будет иметь ту же высоту, что и само изображение.
1.2. Эти 2 элемента в одном контейнере поместите под текстом, который будет накладываться на них.
- См. Приложение 1, следующий GIF-файл, где описаны все эти варианты поведения в сочетании (нажмите здесь, чтобы получить ссылку на веб-сайт):

2. Хотя изображение должно иметь полную ширину и высоту на экранах компьютеров, его размер должен быть ограничен, если соотношение сторон экрана пользователя превышает 16:9 по ширине (например, сверхширокие экраны мониторов 21:9 или при уменьшении масштаба); это будет означать применение максимальной ширины к корневому телу HTML, и изображение должно учитывать это.
- См. Приложение 2.1 и 2.2, чтобы увидеть это поведение (ссылка на веб-сайт для GIF 1 и GIF2):


Как бы четко ни были определены мои собственные требования, я далеко не приблизился к достижению следующего поведения на моем собственном веб-сайте при использовании Компонент изображения Next.js:

- Изображение является блочным элементом, поэтому оно не будет размещаться под текстом
- градиент выше изображения
- Размер изображения: 100vw & 100vh, независимо от того, насколько я уменьшен (и он вообще не предназначен для такой настройки)
Я ломаю голову над этой проблемой уже 3 дня и просто устал от того, как программно получить то, что я хочу. Я прошу, может ли кто-нибудь мне здесь помочь.
Просто для справки (не совсем так, как это будет выглядеть в приведенном ниже коде), это скриншот из старой версии моего раздела «Герой» (1 неделю назад), как я хочу, чтобы раздел «Герой» выглядел

(к сожалению, мне пришлось отказаться от этой версии, поскольку изображение не реагирует и не учитывает ограничение максимальной ширины веб-сайта и размер родительского контейнера из-за свойства fill={true в теге . Но концептуально - я имею в виду концептуально и визуально — так я хочу, чтобы мой главный раздел выглядел.)
Кстати, прежде чем публиковать ответы, я хочу, чтобы ваша настройка была точно такой же, как у меня, чтобы ваш код работал безупречно. Пожалуйста, используйте следующие настройки следующего создания приложения, чтобы сделать его похожим на мой

P.S. Пожалуйста, установите sass через pnpm
Хорошо! Ниже приведены следующие блоки кода по порядку (молюсь, чтобы он не был слишком запутанным):
- globals.scss
- layout.tsx
- heroSection.tsx
- heroSection.module.scss
- page.tsx [где используется HeroSection()]
Код: Выделить всё
/*
NOTE(s):
- This file is renamed from "globals.css" to "globals.scss"
- Minimal change is made to ensure I can default back to Next's default styling when mine breaks
- In cases wherein I must make changes to styling, new classes & IDs are made to use those instead.
*/
:root {
// Next.js defaults
--background: hsl(0, 0%, 100%);
--foreground: hsl(0, 0%, 9%);
/********************************
CUSTOM VARIABLES FOR THIS WEBSITE
********************************/
--defaultBorderRadius: 8px;
--navigationBarHeight: 54px;
--maxScreenWidth: 1280px; // Plan for this is to limit screen size to 16 / 9 aspect ratio
}
@media (prefers-color-scheme: dark) {
// Next.js defaults
// I merged the two @media queries into just one
:root {
--background: hsl(0, 0%, 4%);
--foreground: hsl(0, 0%, 93%);
}
html {
color-scheme: dark;
}
}
html,
body {
/*
Next.js defaults
- "overflow-x" is not used as it breaks horizontal scrolling on the final website
- https://stackoverflow.com/questions/47095596/body-overflow-x-hidden-breaks-position-sticky
*/
max-width: 100vw;
// overflow-x: hidden; // This breaks the NavigationBar(), wherein the sticky property is ignored
overflow-x: clip;
}
body {
// Next.js defaults
color: var(--foreground);
background: var(--background);
// background: black;
font-family: Arial, Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
* {
// Next.js defaults
box-sizing: border-box;
padding: 0;
margin: 0;
}
a {
// Next.js defaults
color: inherit;
text-decoration: none;
}
/***************************************
CLASSES & IDS TAILORED FOR THIS WEBSITE
***************************************/
.pageStructure {
/*
- This sets the final layout of every page of this website
- It's used at the top-level by "@/app/layout.tsx"
- The rest can go either way - in "layout.tsx" or in any "page.tsx" file
*/
display: grid;
grid-template-columns: 1fr;
grid-auto-rows: auto;
}
.sectionHeight {
/*
- Setting to make every section to be as tall as the current screen
- May come into future conflicts, but this is the current settings
*/
min-height: 100vh;
}
.sectionPadding {
/*
- This sets the padding on all pages
- However, it's only applied to each blocks on each page
- As applying this on the root element may possibly break the current page's background
*/
padding: 8px 20px;
}
.navigationBarSpacer {
/*
- The idea is that each page is given the spacing of the navigation bar
- This is so that content won't look squish/short as user scrolls down the page
*/
padding-top: var(--navigationBarHeight);
}
.limitPageSize {
/*
Preferably this is where aspect ratio is limit to 16:9, but I'm at my wit's end on this
*/
max-width: 1280px;
margin: 0 auto;
// background-color: aqua;
}
Код: Выделить всё
export default function RootLayout({
children,
}: Readonly) {
return (
{children} // this is just the HeroSection()
{/* {children} */}
{/* */}
);
}
Код: Выделить всё
import styles from "./heroSection.module.scss";
import Image from "next/image";
export default function HeroSection() {
const backgroundWidth = 800,
backgroundHeight = backgroundWidth / (16 / 9);
return (
{/**
* When trying this, use the following picturs linked from below as your "src":
* - https://drive.usercontent.google.com/download?id=1mpHFsyhonKg0JbR3oSgNuCaOIisrDTLf&exp
* - https://drive.usercontent.google.com/download?id=12wBe8M3QPwLFZ5Jj0qpCXJKsNz9ajl3D&exp
*
* Credits belong to "elaymm4 (aka Laymer)"
* Find it hosted here:
* - https://sites.google.com/view/hot-pursuit-challenges/media
*
* In final production, the site will be having a slideshow
* of 4-6 images retrieved remotely (from AWS, Vercel or something similar)
*/}
Lorem ipsum dolor sit amet.
Ipsum qui repudiandae cumque est commodi, rem nihil vel a in!
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sit
deleniti expedita et aliquam placeat ullam totam molestias ipsam
quibusdam beatae numquam odio autem similique natus delectus eius
ratione, soluta voluptate. Lorem ipsum dolor sit amet consectetur
adipisicing elit. Facilis delectus reprehenderit quam omnis, minima
autem eius, ipsum nisi quod totam natus. Dolore ad distinctio eum
iure animi corporis deserunt numquam.
);
}
Код: Выделить всё
$textSectionWidth: 55%;
.main {
// Text color
color: white;
// max-height: 70vh;
}
.bannerContainer {
width: 100%;
height: auto;
background: green;
#image {
z-index: -999;
// Make image brighter
filter: brightness(105%);
/*
Size properties
- Make image fill entire width; auto-adjust height
- Make image 16 / 9 aspect ratio (by defafult)
- Crop image to 1 / 1 aspect ratio on smartphones
*/
width: 100%;
height: 100%;
aspect-ratio: 16 / 9;
object-fit: "cover";
// display: block;
}
#gradient {
height: 100%;
width: 100%;
position: absolute;
// display: block;
/*
In short:
- Have a gradient from left "to right" to make text visible
- Have a gradient from bottom "to top" to make image blend with the background color (set in globals.scss)
*/
background:
linear-gradient(
to right,
black -10%,
hsla(0, 0%, 0%, 0) $textSectionWidth
),
linear-gradient(to top, black 10%, hsla(0, 0%, 0%, 0) 25%);
}
}
.heroTextSection {
// display: none;
// visibility: hidden;
z-index: 999;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(2, 1fr);
place-content: center;
width: calc($textSectionWidth - 5%);
// width: $textSectionWidth;
#heroTitle {
* {
// Make the text LARGE and BOLD
font-size: 3.8rem;
font-weight: 900;
}
}
#heroDescription {
* {
font-size: 2rem;
}
}
#heroMoreInfo {
width: 80%;
* {
text-align: justify;
color: hsl(0, 0%, 90%);
}
font-size: 14px;
}
}
// @media (max-width: globalsVariables.$maxScreenWidth) {
// .main .heroTextSection {
// width: 100%;
// #heroMoreInfo {
// width: 100%;
// }
// }
// }
// @media (max-width: 600px) {
// .bannerContainer {
// #image {
// height: auto;
// }
// }
// }
Код: Выделить всё
import { CSSProperties } from "react";
import Image from "next/image";
// This is simply just a regular div block
// It only incoprporates the standard padding & navigation bar spacing
// Otherwise, nothing more is affected
export const GenericSection = ({
children,
className = "",
id = "",
style = {},
}: Readonly) => {
return (
className={`sectionHeight sectionPadding navigationBarSpacer ${className}`}
// className={`sectionHeight sectionPadding navigationBarSpacer ${className}`}
id={id}
style={style}
>
{children}
);
};
export default function Home() {
// UI Layout
return (
This is the title!
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut dolorum
maiores eveniet omnis cumque esse minus neque ex nulla eum porro
iure laudantium unde quos praesentium, numquam alias aut! A!
This is the title!
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut dolorum
maiores eveniet omnis cumque esse minus neque ex nulla eum porro
iure laudantium unde quos praesentium, numquam alias aut! A!
);
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... ge-compone
Мобильная версия