コーディング練習 中級編:セミナーサイト No.4
今回もパソコンサイトのコーディングです。
前回の続きで「ページトップに戻るボタン」のコーディングと、各ボタンをクリックするとスムーズな動きで各サイトに移動するように実装しました。
スムーズな動きをするプログラムはJavaScriptを使いました。
教材ではjQueryを使っていますが、使わないようにしました。
教材は「無料コーディング練習所」にある「中級編:セミナーサイト」を使いました。
教材の完成版(コーディングしたもの)はこちらです。
課題ではスマホサイトのデザインはありませんでしたので、今回で「中級編:セミナーサイト」は終わりになります。なお、教材の完成版ではスマホサイトのコーディングも実施しており、レスポンシブ対応になっています。
記事の内容は主に練習結果で、作成方法の説明ではありません。
作成したコードは記事の最後に載せています。
メニューの項目とボタンをクリックすると、スムーズな動きで各サイトに移動します。
移動する時間は1秒に設定しています、なお、設定時間は変更することができます。
「ページトップに戻るボタン」はトップ画面から300pxスクロールしたときに現れます。
完成したものは画像では上手く伝えることができないので動画にしました。
動画には音声はありません、無音です。
ご覧いただけましたら幸いです。
テキストエディタは「Cursor(カーソル)」を使っています。
CursorにはコーディングをサポートしてくれるAI機能(ChatGPT)が付いています。無料版を利用しているのでAI機能の使用回数に制限がありますが、無料で利用できる生成AI(ChatGPT、Copilot、Gemini)を使えば無料版でも十分だと思います。
教材として使っている「無料コーディング練習所」のサイトはこちらです。
関連する記事
作成したコードはこちらです。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta property="og:type" content="website" />
<meta property="og:title" content="WDC" />
<meta property="og:url" content="https://webdesigner-go.com/wdc/" />
<meta property="og:description" content="Web Design Conference(WDC)は、最新のWebデザインのトレンドやワーキングスタイルを紹介するイベントを開催。お気軽にご参加ください。" />
<meta property="og:image" content="https://webdesigner-go.com/wdc/img/ogp.png" />
<meta name="description" content="Web Design Conference(WDC)は、最新のWebデザインのトレンドやワーキングスタイルを紹介するイベントを開催。お気軽にご参加ください。" />
<title>WDC</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Noto+Sans+JP:wght@500;700&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet" />
<link href="css/destyle.css" rel="stylesheet" />
<link href="style.css" rel="stylesheet" />
<link rel="icon" type="image/png" href="icon-192x192.png" />
<link rel="apple-touch-icon" type="image/png" href="apple-touch-icon-180x180.png" />
<link rel="icon" href="favicon.ico" />
</head>
<body class="body">
<header class="header">
<div class="header-logo">
<a href="#">WDC</a>
</div>
<nav class="header-nav">
<ul class="header-nav__list">
<li class="header-nav__item">
<a class="header-nav__link header-nav__link--active" href="#about">about</a>
</li>
<li class="header-nav__item">
<a class="header-nav__link" href="#speaker">speaker</a>
</li>
<li class="header-nav__item">
<a class="header-nav__link" href="#session">session</a>
</li>
</ul>
</nav>
</header>
<div class="mv">
<div class="mv-inner">
<div class="mv-titleArea">
<div class="mv-titleArea__subtitle">
Web Design <br class="sp" />Conference vol.24
</div>
<h2 class="mv-titleArea__title">WORK<br />REVOLUTION</h2>
<div class="mv-titleArea__date">2030.05.30</div>
<div class="mv-titleArea-btn">
<a href="#registor" class="mv-titleArea-btn__item">お申し込み</a>
</div>
</div>
<div class="mv-speaker">ショーン・デイビット・ジュニア<span class="mv-speaker__name--small">氏</span><br />
<span class="mv-speaker__name--label">Webデザイナー</span>
</div>
</div>
</div>
<section id="about" class="about">
<div class="about-container">
<div class="about-heading">
<h2 class="about-heading__title">about<span class="about-heading__subtitle">イベントについて</span>
</h2>
</div>
<div class="about-body">
<figure class="about-imgArea">
<img class="about-imgArea__img" src="img/about.jpg" alt="深夜作業の様子" />
</figure>
<div class="about-desc">
<div class="about-desc__subtitle">テーマ</div>
<h3 class="about-desc__title">定時で帰る</h3>
<div class="about-desc__text">
<p>
残業は心と体に良くないです。世界最速で定時に帰る男、ショーン・デイビット・ジュニア氏が定時で帰るためのスペシャルな技を紹介!
さぁ、Let's go home now!
</p>
</div>
<table class="about-table">
<tr class="about-table__row">
<th class="about-table__head">日時</th>
<td class="about-table__data">2030年5月30日(土) 13:00-翌朝13:00</td>
</tr>
<tr class="about-table__row">
<th class="about-table__head">会場</th>
<td class="about-table__data">オンライン</td>
</tr>
<tr class="about-table__row">
<th class="about-table__head">定員</th>
<td class="about-table__data">3名</td>
</tr>
<tr class="about-table__row">
<th class="about-table__head">参加費</th>
<td class="about-table__data">無料</td>
</tr>
</table>
<div class="about-btn">
<a href="#registor" class="about-btn__item about-body-btn__item--sm">お申し込み</a>
</div>
</div>
</div>
</div>
</section>
<section id="speaker" class="speaker">
<div class="speaker-container">
<div class="speaker-heading">
<h2 class="speaker-heading__title">
speaker<span class="speaker-heading__subtitle">スピーカー</span>
</h2>
</div>
<div class="speaker-inner">
<div class="speaker-body">
<div class="speaker-desc">
<h3 class="speaker-desc__name">Shawn David Jr
<span class="speaker-desc__name--smoll">ショーン・デイビット・ジュニア</span>
</h3>
<div class="speaker-desc__text">
<p>
株式会社スタート代表取締役。Webデザイナー。<br />
定時になると仕事用の脳と身体機能が停止し自動的に帰路につく男。ショーン氏のその姿は人間と言うよりもさながらアンドロイドのようである。<br />
ショーン氏は著書『会社ではアンドロイドになれ』の中でこう語っている。<br />
「会社における仕事において、我々は自分を機械、そうアンドロイドと思い込むべきだ。定時になれば自動で仕事用の機能は停止されるのだ。決められた時間に、設定されたタスクのみを行う、それがアンドロイドの役目だろう?そして、それは会社で働く我々人間の権利でもある」<br />
アンドロイドのように働くべきと語るショーン氏の考え方はディストピア思想と揶揄されるが、本イベントでは氏の考え方をたっぷりと味わいたい。
</p>
</div>
</div>
<figure class="speaker-imgArea">
<img class="speaker-imgArea__img" src="img/sean.jpg"alt="ショーン・デイビット・ジュニア"
/>
</figure>
</div>
<div class="speaker-body">
<div class="speaker-desc">
<h3 class="speaker-desc__name">Mihoko Tennis
<span class="speaker-desc__name--smoll">ミホコ・テニース</span>
</h3>
<div class="speaker-desc__text">
<p>
会社員兼プロテニスプレイヤー。WTOランキング63,984位。<br />
会社員をしながらプロテニスプレイヤーとしても生計を立てているミホコ氏。平日は仕事で忙しい中、一体どのようにテニスの練習時間を捻出しているのか?会社にもテニスラケットを持ち込むというミホコ氏のワーキングスタイルに迫る。
</p>
</div>
</div>
<figure class="speaker-imgArea">
<img class="speaker-imgArea__img" src="img/mihoko.jpg" alt="ミホコ・テニース" />
</figure>
</div>
<div class="speaker-body">
<div class="speaker-desc">
<h3 class="speaker-desc__name">Jecica Pannacotta
<span class="speaker-desc__name--smoll">ジェシカ・パンナコッタ</span>
</h3>
<div class="speaker-desc__text">
<p>
フリーランスのエンジニア。<br />「絶対に自宅でフルリモートで働く」という徹底したモットーに基づき、約7年間外出をしていない。インターネットを信仰しており、リアルやオフラインよりもオンラインを最重要視するライフスタイルを実践している。「外に出たら負け」が口グセのジェシカ氏の『超ネット仕事術』は必聴。
</p>
</div>
</div>
<figure class="speaker-imgArea">
<img class="speaker-imgArea__img" src="img/jecica.jpg" alt="ジェシカ・パンナコッタ" />
</figure>
</div>
</div>
</div>
</section>
<section id="session" class="session">
<div class="session-container">
<div class="session-heading">
<h2 class="session-heading__title">
session<span class="session-heading__subtitle">セッション</span>
</h2>
</div>
<table class="session-table">
<tr class="session-tableArea">
<th class="session-tableArea__time">13:00-14:00</th>
<td class="session-tableArea-desc">
<h3 class="session-tableArea-desc__title">ライトニングトーク:定時に帰る、それはアンドロイドになること</h3>
<p class="session-tableArea-desc__text">スピーカー:ショーン・デイビット・ジュニア<br>人間らしくあろうとすること、それが残業を生むのだ。さぁ!アンドロイドになるのだ!</p>
</td>
</tr>
<tr class="session-tableArea">
<th class="session-tableArea__time">14:00-18:00</th>
<td class="session-tableArea-desc">
<h3 class="session-tableArea-desc__title">ショーンのとっておきの定時に帰る方法</h3>
<p class="session-tableArea-desc__text">スピーカー:ショーン・デイビット・ジュニア<br>アンドロイド的定時に帰る方法を紹介。ワタシ、テイジデカエリマス。</p>
</td>
</tr>
<tr class="session-tableArea">
<th class="session-tableArea__time">18:00-24:00</th>
<td class="session-tableArea-desc">
<h3 class="session-tableArea-desc__title">公私混同仕事術</h3>
<p class="session-tableArea-desc__text">スピーカー:ミホコ・テニース<br>私は会社にもテニスラケットを持ち込む。そう、もういっそのこと仕事と趣味の境界線を消しましょう。</p>
</td>
</tr>
<tr class="session-tableArea">
<th class="session-tableArea__time">24:00-13:00</th>
<td class="session-tableArea-desc">
<h3 class="session-tableArea-desc__title">超ネット仕事術</h3>
<p class="session-tableArea-desc__text">スピーカー:ジェシカ・パンナコッタ<br>7年間一度も外出せずに仕事をする方法を紹介。自宅大好きっ!</p>
</td>
</tr>
</table>
</div>
</section>
<section id="registor" class="registor">
<div class="registor-container">
<div class="registor-heading">
<h2 class="registor-heading__title">
registor<span class="registor-heading__subtitle">お申し込み</span>
</h2>
</div>
<div class="registor-form">
<form class="register-inner">
<div class="registor-formArea">
<div class="registor-formArea__title">
ご職業<span class="registor-formArea__title--red">*必須</span>
</div>
<span class="registor-formArea__radio">
<input
type="radio"
id="type01"
name="type"
value="会社員"
checked
/><label class="registor-formArea__radio--label" for="type01">会社員</label></span>
<span class="registor-formArea__radio">
<input
type="radio"
id="type02"
name="type"
value="個人事業主"
/><label class="registor-formArea__radio--label" for="type02">個人事業主</label></span>
<span class="registor-formArea__radio">
<input
type="radio"
id="type03"
name="type"
value="求職中"
/><label class="registor-formArea__radio--label" for="type03">求職中</label></span>
<span class="registor-formArea__radio">
<input
type="radio"
id="type04"
name="type"
value="その他"
/><label class="registor-formArea__radio--label" for="type04">その他</label></span>
</div>
<div class="registor-formArea">
<label for="name" class="registor-formArea__title">お名前
<span class="registor-formArea__title--red">*必須</span></label>
<input
type="text"
id="name"
name="name"
required
class="registor-formArea__input"
/>
</div>
<div class="registor-formArea">
<label for="email" class="registor-formArea__title">メールアドレス
<span class="registor-formArea__title--red">*必須</span></label>
<input
type="email"
id="email"
name="email"
required
class="registor-formArea__input"
/>
</div>
<div class="registor-formArea">
<label for="tel" class="registor-formArea__title">電話番号
<span class="registor-formArea__note">(半角数字ハイフンなし)</span></label>
<input type="tel" id="tel" name="tel" class="registor-formArea__input--tel" />
</div>
<div class="registor-formArea">
<label for="comment" class="registor-formArea__title">スピーカーに質問したいこと</label>
<textarea
id="comment"
name="comment"
placeholder="ご自由にお書きください"
class="registor-formArea__text"
></textarea>
</div>
<div class="registor-formArea">
<label for="job" class="registor-formArea__title"
>WDCをどちらでお知りになりましたか?<span
class="registor-formArea__title--red"
>*必須</span
></label
>
<select id="job" name="job" required class="registor-formArea__select">
<option value="">選択してください</option>
<option value="Google/Yahoo検索">Google/Yahoo検索</option>
<option value="SNS">SNS</option>
<option value="ブログ">ブログ</option>
<option value="友人や知人">友人や知人</option>
<option value="その他">その他</option>
</select>
</div>
<div class="form-btn">
<button type="submit" class="form-btn-item">送信する</button>
</div>
</form>
</div>
</div>
</section>
<footer class="footer">
<div class="footer-copyright">©2030 Web Design Conference</div>
</footer>
<div class="page-top">
<a class="page-top__link"
><span class="page-top__icon material-icons-round">
keyboard_arrow_up
</span>
</a>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>
CSS
@charset "UTF-8";
:root {
--bg-color: #141414;
--bg-gradient: linear-gradient(
135deg,
#0e002e 0%,
#1e092b 23%,
#320c65 49%,
#a01b7c 80%,
#c21780 100%
);
--main-color: #d136d1;
--text-color: #fff;
}
/*--------------------------------
全体
---------------------------------*/
.body {
font-family: "Montserrat", "Noto Sans JP", Arial, "Hiragino Kaku Gothic ProN",
"Hiragino Sans", Meiryo, sans-serif;
font-size: 16px;
letter-spacing: 0.05em;
color: var(--text-color);
background-color: var(--bg-color);
font-feature-settings: "palt";
}
/*--------------------------------
ヘッダー
---------------------------------*/
.header {
display: flex;
position: fixed;
z-index: 10;
align-items: center;
justify-content: space-between;
width: 100%;
height: 90px;
padding: 30px;
}
.header-logo {
font-size: 28px;
font-weight: bold;
line-height: 1;
color: var(--main-color);
}
/* ヘッダーナビ */
.header-nav__list {
display: flex;
position: relative;
align-items: center;
justify-content: center;
column-gap: 30px;
}
.header-nav__item {
font-size: 16px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.header-nav__link {
color: #fff;
text-decoration: none;
}
/*--------------------------------
メインビジュアル
---------------------------------*/
.mv {
background: var(--bg-gradient);
}
.mv-inner {
display: flex;
position: relative;
align-items: center;
max-width: 1240px;
height: 700px;
margin: 0 auto;
padding: 0 50px;
background-image: url(img/mv.png);
background-repeat: no-repeat;
background-position: right bottom;
background-size: 560px 737px;
}
.mv-titleArea {
position: relative;
color: #fff;
}
.mv-titleArea::after {
display: block;
content: "";
position: absolute;
right: 40px;
bottom: 60px;
width: 326px;
height: 68px;
transform: rotate(-13deg);
background-image: url(img/teiji-de-kaerumon.svg);
background-size: contain;
}
.mv-titleArea__subtitle {
font-size: 24px;
font-weight: bold;
line-height: 1;
color: var(--main-color);
margin-bottom: 0.8em;
}
.mv-titleArea__title {
font-size: clamp(24px, 10vw, 100px);
font-weight: bold;
line-height: 1;
margin-bottom: 10px;
}
.mv-titleArea__date {
font-size: 36px;
font-weight: bold;
letter-spacing: 0.07em;
}
.mv-titleArea-btn {
margin-top: 2em;
}
.mv-titleArea-btn__item {
display: inline-block;
position: relative;
width: 300px;
font-size: 18px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: #fff;
text-align: center;
margin: 0 auto;
padding: 24px 0;
transition: all 0.3s;
border-radius: 100px;
background: linear-gradient(135deg, #c41a7f 0%, #664bbf 100%);
box-shadow: 0 10px 0 #dd118e;
}
.mv-titleArea-btn__item:hover {
transform: translateY(4px);
box-shadow: 0 6px 0 #dd118e;
}
.mv-titleArea-btn__item--sm {
width: 230px;
font-size: 18px;
}
.mv-speaker {
position: absolute;
right: 20px;
bottom: 20px;
font-size: 21px;
line-height: 1;
}
.mv-speaker__name--small {
font-size: 0.8em;
}
.mv-speaker__name--label {
font-size: 14px;
}
/*--------------------------------
ABOUT
---------------------------------*/
.about {
padding: 110px 0;
}
.about-container {
max-width: 1170px;
margin: 0 auto;
padding: 0 30px;
}
.about-heading {
text-align: center;
margin-bottom: 60px;
}
.about-heading {
font-size: 60px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: var(--main-color);
text-transform: uppercase;
}
.about-heading__subtitle {
display: block;
font-size: 20px;
color: #fff;
margin-top: 10px;
}
.about-body {
display: flex;
align-items: center;
column-gap: 70px;
}
.about-imgArea {
flex: 0 1 40%;
}
.about-imgArea__img {
max-width: 100%;
height: auto;
vertical-align: bottom;
}
.about-desc {
flex: 1;
}
.about-desc__subtitle {
font-size: 24px;
margin-bottom: 20px;
}
.about-desc__title {
font-size: 48px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.1em;
color: var(--main-color);
margin-bottom: 40px;
}
.about-desc__text {
font-size: 18px;
line-height: 1.8;
margin-bottom: 20px;
}
.about-table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
.about-table__head {
text-align: left;
padding: 5px 0;
}
.about-table__data {
text-align: left;
padding: 5px 0;
}
.about-btn {
margin-top: 20px;
}
.about-btn__item {
display: inline-block;
position: relative;
width: 300px;
font-size: 18px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: #fff;
text-align: center;
margin: 0 auto;
padding: 24px 0;
transition: all 0.3s;
border-radius: 100px;
background: linear-gradient(135deg, #c41a7f 0%, #664bbf 100%);
box-shadow: 0 10px 0 #dd118e;
}
.about-btn__item:hover {
transform: translateY(4px);
box-shadow: 0 6px 0 #dd118e;
}
.about-btn__item--sm {
width: 230px;
font-size: 18px;
}
/*--------------------------------
SPEAKER
---------------------------------*/
.speaker {
background: var(--bg-gradient);
padding: 110px 0;
}
.speaker-container {
max-width: 1170px;
margin: 0 auto;
padding: 0 30px;
}
.speaker-heading {
text-align: center;
margin-bottom: 60px;
}
.speaker-heading__title {
font-size: 60px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: var(--main-color);
text-transform: uppercase;
}
.speaker-heading__subtitle {
display: block;
font-size: 20px;
color: #fff;
margin-top: 10px;
}
.speaker-inner {
display: grid;
row-gap: 80px;
}
.speaker-body {
display: flex;
column-gap: 60px;
}
.speaker-body:nth-child(2n) {
flex-direction: row-reverse;
}
.speaker-desc {
flex: 1;
}
.speaker-desc__name {
font-size: 42px;
font-weight: bold;
line-height: 1;
color: var(--main-color);
margin-bottom: 40px;
}
.speaker-desc__name--smoll {
display: block;
font-size: 18px;
color: #fff;
margin-top: 10px;
}
.speaker-desc__text {
font-size: 16px;
line-height: 1.8;
}
.speaker-imgArea {
flex: 0 1 40%;
}
.speaker-imgArea__img {
max-width: 100%;
height: auto;
vertical-align: bottom;
}
/*--------------------------------
SESSION
---------------------------------*/
.session {
padding: 110px 0;
}
.session-container {
max-width: 1170px;
margin: 0 auto;
padding: 0 30px;
}
.session-heading {
text-align: center;
margin-bottom: 60px;
}
.session-heading__title {
font-size: 60px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: var(--main-color);
text-transform: uppercase;
}
.session-heading__subtitle {
display: block;
font-size: 20px;
color: #fff;
margin-top: 10px;
}
.session-table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
.session-tableArea {
border-bottom: solid 1px #740174;
}
.session-tableArea__time {
font-size: 22px;
width: 200px;
padding: 40px 30px;
}
.session-tableArea-desc {
padding: 40px 30px;
}
.session-tableArea-desc__title {
font-size: 22px;
font-weight: bold;
color: var(--main-color);
margin-bottom: 15px;
}
.session-tableArea-desc__text {
font-size: 15px;
line-height: 1.5;
}
/*--------------------------------
REGISTOR
---------------------------------*/
.registor {
background-image: url(img/bg.jpg);
padding: 110px 0;
}
.registor-container {
max-width: 1170px;
margin: 0 auto;
padding: 0 30px;
}
.registor-heading {
text-align: center;
margin-bottom: 60px;
}
.registor-heading__title {
font-size: 60px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: var(--main-color);
text-transform: uppercase;
}
.registor-heading__subtitle {
display: block;
font-size: 20px;
color: #fff;
margin-top: 10px;
}
.registor-form {
color: #fff;
padding: 90px;
border: 5px solid var(--main-color);
border-radius: 20px;
background-color: #1a1a1a;
}
.registor-formArea__radio--label {
margin-left: 5px;
}
.registor-formArea:not(:last-child) {
margin-bottom: 30px;
}
.registor-formArea__title {
display: block;
font-weight: bold;
margin-bottom: 10px;
}
.registor-formArea__title--red {
font-size: 12px;
font-size: 0.75rem;
color: var(--main-color);
margin-left: 10px;
}
.registor-formArea__radio:not(:last-child) {
margin-right: 35px;
}
.registor-formArea__input {
width: 300px;
color: #333;
padding: 8px;
border: solid 1px #aaa;
border-radius: 5px;
background-color: #fff;
}
.registor-formArea__input--tel {
width: 200px;
color: #333;
padding: 8px;
border: solid 1px #aaa;
border-radius: 5px;
background-color: #fff;
}
.registor-formArea__note {
font-size: 12px;
font-size: 0.75rem;
font-weight: normal;
margin-left: 5px;
}
.registor-formArea__text {
min-width: 600px;
min-height: 200px;
color: #333;
padding: 8px;
border: solid 1px #aaa;
border-radius: 5px;
background-color: #fff;
resize: both;
}
.registor-formArea__select {
width: 300px;
color: #333;
padding: 8px;
border: solid 1px #aaa;
border-radius: 5px;
background-color: #fff;
}
.form-btn {
text-align: center;
margin-top: 50px;
}
.form-btn-item {
display: inline-block;
position: relative;
width: 300px;
font-size: 18px;
font-weight: bold;
line-height: 1;
letter-spacing: 0.05em;
color: #fff;
text-align: center;
margin: 0 auto;
padding: 24px 0;
transition: all 0.3s;
border-radius: 100px;
background: linear-gradient(135deg, #c41a7f 0%, #664bbf 100%);
box-shadow: 0 10px 0 #dd118e;
}
.form-btn-item:hover {
transform: translateY(4px);
box-shadow: 0 6px 0 #dd118e;
}
/*--------------------------------
フッター
---------------------------------*/
.footer {
display: grid;
color: #fff;
padding: 70px 20px;
background-color: #141414;
place-items: center;
}
.footer-copyright {
font-size: 14px;
font-weight: bold;
letter-spacing: 0.08em;
}
/*--------------------------------
ページトップ
---------------------------------*/
.page-top {
display: none;
position: fixed;
right: 40px;
bottom: 40px;
z-index: 1;
}
.page-top__link {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 80px;
color: #fff;
text-align: center;
text-decoration: none;
transition: opacity 0.3s;
border-radius: 50%;
background: linear-gradient(135deg, #c41a7f 0%, #664bbf 100%);
cursor: pointer;
}
.page-top__icon {
font-size: 40px;
}
.page-top__link:hover {
opacity: 0.8;
}
JavaScript
// スムーズスクロール関数
function smoothScroll(target, time) {
let start = window.scrollY;
let distance = target - start;
let startTime = null;
function animation(currentTime) {
if (startTime === null) startTime = currentTime;
let timeElapsed = currentTime - startTime;
let run = ease(timeElapsed, start, distance, time);
window.scrollTo(0, run);
if (timeElapsed < time) requestAnimationFrame(animation);
}
function ease(t, b, c, d) {
t /= d / 2;
if (t < 1) return c / 2 * t * t + b;
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
}
// t:現在の時間(アニメーションが開始してからの経過時間)
// b:開始時点の値
// c:変化する値(終了値 - 開始値)
// d:アニメーションの総時間
requestAnimationFrame(animation);
}
// ページ内スクロール
document.querySelectorAll('a[href^="#"]').forEach(function (element) {
element.addEventListener('click', function (event) {
event.preventDefault();
let href = this.getAttribute("href");
let target = document.querySelector(href === "#" || href === "" ? 'html' : href);
let position = target.getBoundingClientRect().top + window.scrollY;
smoothScroll(position, 1000); // 1000 = 1秒
});
});
// ページトップへ戻る
let pageTop = document.querySelector('.page-top');
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
pageTop.style.display = "block";
} else {
pageTop.style.display = "none";
}
});
pageTop.addEventListener('click', function (event) {
event.preventDefault();
smoothScroll(0, 1000); // 1000 = 1秒
});
この記事が参加している募集
よろしければサポートお願いします!いただいたサポートはクリエーターとしての活動費に使わせていただきます!