Создаем лендинг сайт с нуля: якорные ссылки меню #11

1 июня 2025
3 минуты

Сегодня настроим якорные ссылки для всех пунктов меню и кнопки «Перейти в каталог», это позволит использовать навигацию по нашему сайту, также проведем небольшой рефакторинг кода и вынесем некоторые части кода в отдельные компоненты для последующего удобства работы с ними.

превью | blog.in9var.ru
Превью | blog.in9var.ru

Полезные ссылки:

Демо–проект лендинга можно посмотретьпо ссылке
Часть 1. Подготовка и настройка проекта
Часть 2.Настройка конфигурации и установка необходимых библиотек
Часть 3.Создание CSS-переменных и верстка блока Header
Часть 4.Верстка секции Hero, создание компонента Button
Часть 5.Верстка секции About
Часть 6.Верстка секции Gallery
Часть 7.Верстка секции WhyUs
Часть 8.Верстка секции Catalogue
Часть 9.Верстка секции Map
Часть 10.Верстка секции Footer
Часть 11.Создание якорных ссылок, рефакторинг
Часть 12.Создание мобильного меню
Часть 13.Анимация секций при скролле
Часть 14.Установка метаданных
Часть 15.Настройка favicon.ico
Часть 16.Настройка счетчика Яндекс Метрики
Часть 17.Публикуем проект на хостинге
  • Шаблон лендинга, который мы будем делать, доступен в Figma по ссылке.
  • Код данного урока доступен в репозитории GitHub по ссылке.
  • Подписывайтесь на мой Дзен канал

Якорные ссылки

У нас в шаблоне есть ссылки в верхнем и нижнем меню, а также кнопка, ссылающаяся на секцию каталога.

Для начала нам необходимо проставить id на те секции, на которые мы будем направлять ссылку, делается это очень просто, нам необходимо в перечисленных файлах указать уникальный идентификатор id.

Я не буду вставлять весь код каждого файла, просто перечислю их названия и отрывок кода.

page.jsx

... <main id='main'> ...

WhyUs.jsx

... <section id='about' className='flex w-full text-on-secondary bg-secondary'> ...

Catalogue.jsx

... <section id='products' className='w-full px-5 mx-auto max-w-screen-xl py-12 lg:py-32'> ...

Map.jsx

... <section id='contacts' className='flex w-full text-on-primary bg-primary'> ...

Теперь все ссылки вида «/#название_якоря» будут перемещать нас в необходимую секцию. Всё достаточно просто.

Компонент логотипа Logo.jsx

У нас на сайте есть повторяющийся элемент логотипа, чтобы не дублировать код и редактировать его из одного места, создадим в папке app/components/elements/ компонент Logo.jsx.

Содержимое файла Logo.

import Link from 'next/link'; export default function Logo({ href }) { return ( <Link href={href} className='font-black text-4xl'> Логотип </Link> ); }

Теперь в Header.jsx и Footer.jsx мы можем импортировать наш новый компонент Logo.jsx и удалить часть старого кода.

... <Logo href={'/'} /> ...

Социальные иконки

Социальные иконки у нас также дублируются в Header.jsx и Footer.jsx. Создадим компонент Icon.jsx в папке app/components/elements/ и поместим в него следующий код:

import Link from 'next/link'; import { IoMdMail } from 'react-icons/io'; import { BiLogoTelegram } from 'react-icons/bi'; export default function Icon({ href, type }) { return ( <Link href={href}> <div className='flex bg-primary hover:brightness-110 rounded-md text-on-primary p-2 transition-all duration-200 ease-in-out'> {type === 'email' && <IoMdMail className='flex bg-primary rounded-md text-on-primary' size={18} />} {type === 'telegram' && <BiLogoTelegram className='flex bg-primary rounded-md text-on-primary' size={18} />} </div> </Link> ); }

Данный компонент принимает в качестве параметров ссылку — href и тип — type, и на основании этого возвращает необходимую иконку с соответствующей ссылкой.

Теперь нам не надо редактировать в двух частях сайта код при изменении, например, адреса электронной почты.

Создадим компонент SocialIcons.jsx в папке app/components/blocks/.

Код данного компонента:

import Icon from '../elements/Icon'; export default function SocialIcons() { return ( <div className='flex gap-6 items-start'> <Icon href={'mailto:mail@email.ru'} type='email' /> <Icon href={'tg://resolve?domain=@someTgAccountName'} type='telegram' /> </div> ); }

В этом компоненте мы размещаем иконки нужного типа в необходимом порядке.

Остается только обновить наши компоненты Header.jsx и Footer.jsx. Убираем из них старый кусок кода с иконками и вставляем наш компонент блока SocialIcons.jsx.

... <SocialIcons /> ...

Компонент ProductCard.jsx

Я решил вынести карточку товаров в отдельный компонент для удобства.

Создаем файл ProductCard.jsx в папке app/components/blocks/

код компонента ProductCard.jsx:

import ExportedImage from 'next-image-export-optimizer'; export default function ProductCard({ item }) { return ( <div className='flex flex-col gap-5'> <div className={`aspect-[4/3] overflow-hidden relative`}> <ExportedImage alt={'card image'} src={item.src} fill loading='lazy' placeholder='blur' className={`object-cover`} /> </div> <div className='flex flex-col gap-3'> <h3 className='text-xl font-black'>{item.title}</h3> <div className='flex justify-between'> <div className='flex flex-col gap-3'> <span className='font-black'> <span className='font-light '>Площадь: </span> {item.area}&nbsp;м² </span> <span className='font-black'> <span className='font-light '>Этажи: </span> {item.floors} </span> </div> <div className='flex flex-col gap-3 items-end'> <span className='font-black'> <span className='font-light '>Спальни: </span> {item.bedrooms} </span> <span className='font-light '> {item.material}</span> </div> </div> <span className='text-xl font-black'>{`${item.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ')} ₽`}</span> </div> </div> ); }

Теперь можем почистить компонент Catalogue.jsx.

код компонента Catalogue.jsx:

import { cardItems } from '@/app/cardItems'; import ProductCard from '../blocks/ProductCard'; export default function Catalogue() { return ( <section id='products' className='w-full px-5 mx-auto max-w-screen-xl py-12 lg:py-32'> <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-14 lg:gap-10 w-full'> {cardItems.map((item, index) => ( <ProductCard key={index} item={item} /> ))} </div> </section> ); }

После всех этих манипуляций код стал намного чище, и его гораздо удобнее рефакторить и поддерживать.

В следующей статье займемся BurgerMenu и заставим его работать на мобильных устройствах.

На сегодня всё!

В следующей статье мы сверстаем секцию Gallery.

Шаблон лендинга, который мы будем делать, доступен в Figma по ссылке.

Код данного урока доступен в репозитории GitHub по ссылке.

На этом всё, добавляйте сайт в избранное, чтобы не пропустить новых статей, а также подписывайтесь на мой Дзен-канал – dzen.ru/in9var