独学でコーディング学習を進める上で、大いに参考にさせていただいている「しょーごログ」(https://shogo-log.com/coding-study/)というサイトがあります。こちら、デザインカンプが提示され、そのデザインどおりの見た目になるように、HTML/CSS/JavaScriptによるコーディングをし、結果をプロのエンジニアに添削してもらえる、というサービスです。
さらに、中級以上の演習課題に関しては、カンプ通りのコーディングに加えて、そのカンプのデザインを踏襲して自分でオリジナルの画像・文言を構成した「オリジナルサイト」を作成する、という演習も必須になっており、自分がサイトを構築するうえでの適切な画像の選び方や伝わる文言のレイアウトなどを学べるような仕組みになっています。
しょーごログのコーディング演習課題ページ→https://shogo-log.com/coding-study/
今回、この演習課題の「中級ー農園サイト」を完了し、さらにその応用である「オリジナルサイト」を作成しましたので備忘録的にコードの中身を解説していきます。(中級課題はしょーごさんレビューで合格済み、オリジナルサイトもしょーごさんのレビューを受け終わったものになります)コーディングの一例としてご参考になれば幸いです。
全体構成
完成したサイトはこちら
認証画面が出るので
ID→flower01
パスワード→flower01#
を入力してください。
しょーごログでの中級課題「農園サイト」をオリジナルに改変した、「フラワーデリバー」というお花お届けサービスの仮想サイトになります。
ページは、以下のセクションで構成されています。
ファーストビュー
メニュー
サービス概要とキャッチフレーズ
商品ラインナップ(Swiperによるメニューのカルーセル処理)
ニュース
FAQ(Jsを使用して、アコーディオンメニューとした)
アクセス(実店舗の紹介)
お問い合わせフォーム
フッター
上記のセクションの合間に花の画像を左右に配置してあったり、サービス概要部分は文章と画像をわざとずらした配置にしていたり、レスポンシブ対応が求められたりと、課題自体の難易度はかなり高く、苦戦しました。
今回はこの課題を利用したオリジナルサイトを、sassを使ってなるべく共通化、パーツ化しながら、コーディングしていきたいと思います!
SCSSのプランニング
共通化、パーツ化をめざしてsassを利用するにあたっては、
「【Dart Sass対応】LPをつくって学ぶSass×FLOCSS」https://zenn.dev/yurukei20/books/10e7322a762178
を大いに参考にさせていただきました。この無料のチュートリアルに沿ってクラス名を命名したので
命名がルール化され、重複したり「あれ、どこのスタイル用のクラス名だっけ?」という混乱がかなり減りました。
また、このチュートリアルを参考に、今回のサイト構成に沿って作成したファイルの構造は、以下の通りです。
└─flower
├─index.html
├─thanks.html(問い合わせフォームで送信ボタンをおしたあとに遷移するページ)
├─favicon.ico
├─css
├─style.css(style.scssからコンパイルされるcss)
└─style.css.map
├─img
└─scss
├─foundation(サイト全体のフォント設定・カラー設定・レスポンシブにおけるブレイクポイント)
├─_reset.scss(いわゆるリセットcss)
├─_base.scss
├─_color.scss
├─_font.scss
├─_maxbreakpoints.scss
└─_index.scss
├─component(サイト内の共通パーツのスタイル設定)
├─_logo.scss
├─_productcard.scss
└─_index.scss
├─project(サイト内各セクションごとのスタイル設定)
├─_feature.scss
├─_news.scss
├─_faq.scss
├─_access.scss
├─_contact.scss
├─_form.scss
└─_index.scss
└─_utility.scss(セクションに含まれない部分のスタイル)
├─_layout.scss(ファーストビューや、各セクション共通のスタイル)
├─_spmenu.scss(ハンバーガーメニューまわりのスタイル)
├─_loading.scss(ローディング画面のスタイル)
└─style.scss(foundation,component,project各フォルダ内の_index.scssと、
_utility,_layout,_spmenu,_loadingの各scssを合成して、最終的に
style.cssにエクスポートするscss)
思いのほか壮大なツリー図になってしまって「ウゲッ」という感じですが、ざっくり言うと
1.scssフォルダ内の子フォルダfoundation、compornent、projectに関しては、その中の 「_index.scss」にそれ以外のscssの内容をまとめる
2.子フォルダがないscssに関しては、「style.scss」にその内容をまとめる、という構造になっています。
そうすることによって、各パーツ(ロゴだったり、フォームだったり)のスタイルがひとつのscssファイルとして独立することになります。
つまり、一度作れば、他のサイトがサイトの構成や内容は異なっても、パーツとして利用することができるので、使いまわししやすくなるのでは・・?と考えました。
レスポンシブ対応~ブレイクポイントの指定~
このサイトでは、PC表示ファースト(1200px以上)でコーディングしています。また、ブレイクポイントを以下のように設定しました。
- 1100px以下 ABOUTセクションの画像とテキストが重なりすぎないようにする
- 768px以下 一番レイアウトを変更しているポイント。全体的にこの幅以下がいわゆる「スマホレイアウト」。トップ画像のテキストを横書きに。メニューをハンバーガーメニューとする
- 580px以下 ABOUTセクションの文言エリアをちょっとブラウザ幅に対して広くとった
- 380px以下 トップ画像のテキストエリアの位置を修正
「デスクトップ表示」「スマホ表示」として一番初めに設定したブレイクポイントは768pxで、あとのポイントはコーディングした結果をブラウザで確認しながら、ちょっと手直ししたほうがいいかな・・・という観点で追加していったポイントになります。
実際のメディアクエリの記述は、ブレイクポイントを変数(マップ)で定義しています。
_maxbreakpoints.scss を作成し、ここで、変数sm/sl/md/lg/xl(xlは実際の使用はなし)を定義。
// breakpoint
// ------------------------------
$breakpoints: (
"sm": 380px,
"sl": 580px,
"md": 768px,
"lg": 1100px,
"xl": 1200px,
);
@mixin mq($breakpoint: md) { ←ブレイクポイントの初期値を「md」にしています
@media screen and (max-width: #{map-get($breakpoints, $breakpoint)}) {
@content;
}
}
これを、実際にメディアクエリを設定したいところで以下のように書いて、呼び出しています。
@use "foundation/maxbreakpoints" as bp;
@include bp.mq{
//初期値であるmd(768px)以下のスタイルを指定
}
@include bp.mq(sm){
//sm(380px)以下のスタイルを指定
}
「Sass」「メディアクエリ」「マップ」などで検索すると解説されているサイトが見つかるので、そちらも参照してみてください。たとえば
「Sassのmixinでメディアクエリを管理する」 https://blanche-toile.com/web/sass-media-queries-mixin
など
ヘッダー部分(ファーストビュー~メニュー)
ファーストビュー写真と、その下のお店のロゴを中央に配置したメニュー部分です。
ロゴ部分
.c-logo というロゴ部品用のスタイルを設定しました。このスタイルはフッターのロゴ部分にも使いまわしています。
ロゴの透過画像「logomark.png」をborder-radius50%の薄ピンクの正円に重ねた「丸の部分」を
店名文字ロゴ「logo.png」をmax-width300px,height100pxの薄ピンク地にしたaタグのbefore要素にして組み合わせました。レスポンシブ対応にするため、丸の大きさや文字部分との重なりなどはvwに比例して変化するようにしています。(clampを使用しました。細かい数値は試行錯誤で決めています)
ロゴのHTML(花模様もお店の名前も透過png画像で作っているのでHTML的にはシンプルです)
<a class="c-logo" href="#" ></a>
SCSS
.c-logo{
display:inline-block; ←a要素に幅と高さを設定するため
background-color:var(--color-bg-primary); ←このサイトの背景色である薄ピンク色のことです
background-image:url(../img/logo.png); ←「FLOWER DELIVER お花のお届けサブスクリプション」の組み文字を透過画像にしています
background-size: contain;
background-repeat:no-repeat;
width:98vw;←レスポンシブ対応のため、横幅はブラウザ幅に依存して変化するようにしました
max-width:300px; ←横幅の最大値
height:100px; ←縦幅は固定
position: relative; ←before要素と重ねるため
z-index:1; ←丸部分よりも手前に配置
&::before{
content:"";
background-color:var(--color-bg-primary);
width:clamp(100px,30vw,154px); ←円の大きさ。これもレスポンシブ対応のため、ブラウザ幅に依存していますが
最小値と最大値は決めています
aspect-ratio: 1 / 1; ← これで高さを決めています
border-radius:50%;
background-image:url(../img/logomark.png); ←花模様の透過画像
background-size: 80%; 花模様画像の大きさの設定 正円の大きさに比べて80%にしました
background-repeat: no-repeat;
background-position: center;
position:absolute; ←ここから4行で店名部分との重なりを設定。左右中央かつちょっと正円が店名に重なりつつ上にくるように
left:50%;
transform:translateX(-50%);
top:clamp(-150%,-30vw,-90%); ←このへんの数値は試行錯誤です。
}
}
トップ画像とナビゲーション部分
HTML
ページの見た目は「ファーストビュー写真」の下に「メニュー」がありますが、HTML上ではメニュー部分を最初に書いています。
<header>
<nav class="l-nav">
<ul class="l-nav__contents">
<li class="l-nav__item"><a href="#feature">ABOUT</a></li>
<li class="l-nav__item"><a href="#products">LINEUP</a></li>
<li class="l-nav__item"><a href="#news">NEWS</a></li>
<li><a class="c-logo" href="#" ></a></li>
<li class="l-nav__item"><a href="#faq">FAQ</a></li>
<li class="l-nav__item"><a href="#access">ACCESS</a></li>
<li class="l-nav__item"><a href="#contact">CONTACT</a></li>
</ul>
</nav>
<div class="l-top">
<div class="l-top__textcontainer">
<h1 class="l-top__text"><span class="bgcolor">はじめませんか</span></h1><h1 class="l-top__text"><span class="bgcolor">毎日を彩る</span></h1><h1 class="l-top__text"><span class="bgcolor">お花のある暮らし</span></h1>
</div>
</div>
</header>
SCSS
header{
display:flex;
flex-direction: column-reverse;
}
.l-top{
width:100%;
aspect-ratio: 100 / 67; ←トップ画像を表示するエリア。写真が縦に伸びたり横に伸びたりしないようにきっちり比を設定。
background-image:url(../img/fv.jpg); ←トップ画像(写真)は背景画像として指定しています
background-size: cover;
background-position: center;
&__textcontainer{ ←「はじめませんか」「毎日を彩る」「お花のある暮らし」のテキストのかたまり
display: flex;
flex-direction: row-reverse; ←縦書きのテキストが右から左に配置されるように
gap:0.4em;
position:absolute;
top:5vw;
left:10vw;
@include bp.mq(md){ ←タブレットやスマホでの表示。テキストを横書きにしたので、配置も変えています。
all:initial;
width:70%;
display: flex;
flex-direction: column;
position: absolute;
/* テキストを画像のどこに配置するかを設定 */
top:38vw;
left:6vw;
transform: translateY(-20vw);
}
@include bp.mq(sm){
left: 4px;
}
}
&__text{
-ms-writing-mode: tb-rl;
writing-mode: vertical-rl; ←縦書きにする指定
line-height: 62px;
letter-spacing: 20px;
font-size:min(3.6vw,40px); ←フォントサイズは最大40pxとし、ブラウザ幅に応じて可変としました
@include bp.mq(md){ ←タブレットやスマホでのテキストは横書きにしました。いったん「all:initial」で設定を全部白紙にしてから
改めてフォントから指定しなおしています
all:initial;
font-family: 'Noto Sans JP', sans-serif;
color:#4E301B;
/* よこ書き */
font-size:clamp(14px, 4.4vw,28px);
font-weight:700;
// line-height: 1.4;
letter-spacing:0.1em;
padding:0.3em;
}
}
span{
padding-top:8px;
background-color: var(--color-bg-primary);
@include bp.mq(lg){
padding:0.1em;
}
}
}
.l-nav{
background-color: var(--color-bg-primary);
&__contents{
width:90%;
max-width:1100px;
margin:40px auto 0;
display:flex;
justify-content: space-between;
align-items:center;
@include bp.mq{
justify-content: center;
}
}
&__item{
font-size:clamp(10px, 1.5vw,16px); ←ウィンドウ幅が狭くなっても、メニューが重ならないように
font-weight:700;
@include bp.mq{
display:none; ←タブレット表示(768px)以下ではハンバーガーメニューにしたので、メニューリストは非表示
}
}
}
スマホレイアウトのハンバーガーメニュー部分
ハンバーガーメニューのデザインや動きの部分です。scssを活用することで、関係するスタイルは「_spmenu.scss」というファイルにまとめて、他のサイトでハンバーガーメニューを実装するときに使いまわししやすいようにしました。また、このサイトを作成した時点では自分がまだJsについて理解が浅かったこともあり、手っ取り早くjQueryを使用しています。
コーディングにあたっては、得意の「先人に学ぶスタイル」(笑)。「ハンバーガーメニュー 作り方」などでググって、以下のページなどを参考にしました(改めて読み返すと私のコードは中途半端だということが分かりましたが・・これから作る方はshibajukuさんの解説通り、アクセスビリティにより配慮されると良いと思います)
HTML
<!-- スマホのハンバーガーメニュー -->
<section class="l-spmenu">
<button type="button" id="js-hamburger" class="l-spmenu__button c-js-btn c-hamburger" aria-controls="js-global-menu" aria-expanded="false" aria-label="メニューを開閉する">
<span class="c-hamburger__line">
</span>
</button>
<div class="l-spmenu__modalmenu" id="js-global-menu" aria-hidden="true">
<div class="c-logo c-logo-modal">
</div>
<nav>
<ul>
<li class="l-spmenu__menuitem"><a href="#feature">ABOUT</a></li>
<li class="l-spmenu__menuitem"><a href="#products">LINE UP</a></li>
<li class="l-spmenu__menuitem"><a href="#news">NEWS</a></li>
<li class="l-spmenu__menuitem"><a href="#faq">FAQ</a></li>
<li class="l-spmenu__menuitem"><a href="#access">ACCESS</a></li>
<li class="l-spmenu__menuitem"><a href="#contact">CONTACT</a></li>
</ul>
</nav>
</div><!-- /.sp-header-menu-->
<!-- モーダル座布団 -->
<div class="c-modal-background" id="js-modal-background"></div>
<!-- /.modal-background -->
</section>
<!-- スマホのハンバーガーメニュー ここまで -->
SCSS
// spメニューとメニューボタンの表示・非表示
.l-spmenu{
display:none;
@include bp.mq{
display:block;
}
&__button{
display: inline-block;
text-decoration:none;
-webkit-appearance:none;
-moz-appearance: none;
appearance:none;
border:none;
background-color:tranceparent;
cursor:pointer;
}
}
.is-modalActive{
.l-spmenu__modalmenu{
visibility: visible;
opacity: 1;
transition: 0.3s;
}
.c-modal-background{
visibility:visible;
opacity:0.8;
transition: 0.3s;
}
}
// ハンバーガーメニューボタンの実装
.c-hamburger{ ←ボタンの「丸」の部分のスタイル
position:fixed;
top:20px;
right:20px;
z-index:15;
width: 48px;
height: 48px;
border-radius:50%;
background-color:var(--color-bg-footer-gray);←実際の色は薄いピンクです
box-shadow:0 3px 6px rgba(0,0,0,0.16);
outline:none;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
&:hover{
box-shadow: 0 3px 8px rgba(0,0,0,0.5);
}
&__line{ ←ボタン内部の横三本線の部分です。一番上の線は「::before」一番下の線は「::after」で設定。
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin:auto;
width: 18px;
height: 2px;
background-color: #4E301B;
-webkit-transition: inherit;
transition:inherit;
&::before{
position: absolute;
display:block;
width: 100%;
height: 100%;
background-color:inherit;
content:"";
-webkit-transition: inherit;
transition: inherit;
top:-5px;
}
&::after{
position: absolute;
display:block;
width: 100%;
height: 100%;
background-color:inherit;
content:"";
-webkit-transition: inherit;
transition: inherit;
top:5px;
}
}
}
.c-hamburger[aria-expanded = true]{ ←メニューボタンをクリックしたとき。真ん中の線は透明に。上下の線は斜めにするこ
とで「バッテン」に変化するように見えます
.c-hamburger__line{
background-color:transparent;
&::before{
top: 0;
background-color: #4E301B;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
&::after{
top: 0;
background-color: #4E301B;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
}
}
.c-modal-background{ ←ハンバーガーメニューを開いたときに画面を覆う部分です
position: fixed;
z-index:9;
width:100vw;
top:0;
right:0;
bottom:0;
height:100vh;
overflow:hidden;
background-color:var(--color-bg-primary);
color:#4e301b;
visibility: hidden;
opacity:0;
transition: 0.3s;
}
// SPメニュー画面そのもの
.l-spmenu{
&__modalmenu{
position: fixed;
z-index:14;
width: 100vw;
height:100vh;
top:20px;
right:0;
bottom:0;
overflow: hidden;
background-color: transparent;
visibility: hidden;
opacity: 0;
transition: 0.3s;
text-align: center;
}
&__menuitem{
color: #4E301B;
font-size: 16px;
padding:8px;
font-weight: 700;
}
}
JavaScript
ハンバーガーボタンや背景をクリックすることで、以下の動作をさせています。
・body全体に「is-modalActive」というクラスを付与/はずす
(is-modalActiveクラスが付与されると、メニュー画面とメニューのざぶとんが表示されます)
・aria-expandedの「false」と「true」を逆のものにする
(trueのときにボタンの三本線がバッテン印になります)
// SP用モーダルメニュー jQuery使用
$(function(){
$('.l-spmenu__button').click(function(){
$('body').toggleClass('is-modalActive');
// 属性の設定attrを使う
if ($(this).attr('aria-expanded') == 'false'){
$(this).attr('aria-expanded', true);
$('#js-global-menu').attr('aria-hidden', 'false');
}else{
$(this).attr('aria-expanded' , 'false');
$('#js-global-menu').attr('aria-hidden', 'true');
}
});
// 背景クリックでメニューが消えるようにする
$('#js-global-menu').click(function(){
$('body').removeClass('is-modalActive');
$('#js-hamburger').attr('aria-expanded', 'false');
$('#js-global-menu').attr('aria-hidden' , 'true');
});
// リンクをクリックした時もメニューが消えるようにする
$('a[href^="#"]').click(function(){
$('body').removeClass('is-modalActive');
$('#js-hamburger').attr('aria-expanded', 'false');
$('#js-global-menu').attr('aria-hidden' , 'true');
});
});
ABOUT」セクション
このセクション(ナビゲーションメニュー上「ABOUT」となっている部分ですが、クラス名を付けるときに間違えて「feature」としてしまいました)は、当時学習したてだった「gridレイアウト」で実装してみました。
上図にあるように、タイトルと文章、画像2つの合計4つの要素をコンテナで囲み、display:gridを指定。
画像とテキストが重なる部分は、画像の幅を親要素(column2から3までの幅)からはみ出すよう指定してみました。(width:140%とした部分)。要素のwidth指定などは試行錯誤だったため、膨大な時間がかかり「やめりゃよかった・・・と途中後悔も(汗)。ですが、PCレイアウトを2種類つくったこと、それらとスマホレイアウトを結構異なるデザインにしたので、結果的にはなかなか良かったと思います。
HTML
画像はHTMLでは指定せず、divで範囲設定したところの背景画像という形でscssで指定しています。
span祭りになっているのは、ブラウザ幅を広くしたり狭くしたりしても、文章の区切りのよいところで改行させたかったためです。とはいえ区切る箇所が多すぎた気もする・・・
<!-- featureセクション 農園の想い・キャッチフレーズ -->
<section id="feature" class="p-feature ">
<div class="l-inner-feature" data-aos="fade-up">
<div class="p-feature__container">
<h1 class="p-feature__title">四季折々の花と緑を、<span class="u-nowrap">お届けします</span></h1>
<div class="p-feature__contents">
<p class="p-feature__text">「FlowerDeliver」は、</span><span class="u-nowrap">四季おりおりの花束や </span><span class="u-nowrap">アレンジメントを</span><br><span class="u-nowrap">隔週でご自宅にお届けする</span>
<span class="u-nowrap">サービス。</span>
<span class="u-nowrap">一度お申込みいただくだけで</span><br><span class="u-nowrap">ふだんの暮らしを彩る</span><span class="u-nowrap">キレイなお花のある暮らしが<span class="u-nowrap">実現します。</span></span><br><br><span class="u-nowrap">一緒にお届けするカードには</span><br><span class="u-nowrap">身の回りの小物をつかったアレンジの例や<br>長持ちする生け方のヒントも。</span><br><span class="u-nowrap">初めての方にもお気軽に</span><span class="u-nowrap">たのしんでいただけます。</span><br><br><span class="u-nowrap">ギフトとしてのお届けにも対応</span><br><span class="u-nowrap">大切な方への贈り物にも</span><br><span class="nu-owrap">最適です。</span><br><br><span class="u-nowrap">さあ、あなたもお気軽に</span><span class="u-nowrap">花のある暮らしを</span><br><span class="u-nowrap">たのしんでみませんか。</span>
</p>
</div>
<div class="p-feature__img1">
</div>
<div class="p-feature__img2"></div>
</div>
</div> <!-- /l-inner-wide -->
</section>
<!-- ---------------------------------- -->
SCSS
.l-inner-feature{
max-width:1600px; ←ウィンドウ幅が広いときに際限なくインナーコンテンツが端に寄ってしまわないよう設定。
margin:0 auto;
}
.p-feature{
background-color: var(--color-bg-primary);
&__container{
max-width:1100px;
min-height:780px;
margin:0 40px 0 auto; ←ウインドウ幅が広いときには、このセクション全体が気持ち右寄せになるようにしています。
padding:0 20px ;
display:grid;
grid-template-columns: repeat(2,1fr);
grid-template-rows:100px 1fr;
@include bp.mq(lg){
margin:0 auto;
}
@include bp.mq{
display:flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
}
&__title{
position:relative; ←テキストと画像が重なるので、positionの指定が必要
background-color:rgba(255,255,255,0.9);
color:var(--color-font-feature);
line-height:1.44;
width:75%;
margin-top:40px;
padding-left:8px;
grid-column: 1/3;
grid-row:1/2;
@include bp.mq(lg){
width:90%;
font-size: clamp(20px,3.6vw,40px); ←40px固定のままだとウィンドウ幅が狭いときにフォントが巨大に
なってしまうので、幅に依存するようにしました。ブレイクポイントの1100px
のときに40pxにしたかったので、40/1100=3.6vwとしています。
}
@include bp.mq{
order:1;
width:85%;
align-self:center;
text-align: center;
}
}
&__contents{
position: relative;
width:100%;
grid-column: 1/2;
grid-row: 2/3;
margin-top:40px;
padding:8px;
@include bp.mq(lg){
grid-column: 1/3;
width:65%;
margin-top:200px;
}
@include bp.mq{
width:85%;
order:3;
margin:0;
text-align:center;
}
@include bp.mq(sl){
width:100%;
}
}
&__text{
background-color:rgba(255,255,255,0.9);
font-size:16px;
line-height:2.0;
padding-left:4px;
}
&__img1{
grid-column: 2/3;
grid-row: 1/2;
background-color:var(--color-bg-primary);
width:140%;
justify-self: end;
aspect-ratio: 3 / 2;
border-radius:150px;
background-image:url(../img/about-01.jpg);
background-position: center;
background-size:cover;
@include bp.mq{
width: 85%;
order:2;
}
}
&__img2{
grid-column:2/3;
grid-row: 2/3;
justify-self: end;
align-self:end;
background-color:var(--color-bg-primary);
width:70%;
aspect-ratio: 3 / 2;
border-radius:50px;
background-image:url(../img/about-02.jpg);
background-position: center;
background-size:cover;
@include bp.mq(lg){
width:85%;
}
@include bp.mq{
width: 85%;
order:4;
align-self: center;
}
}
}
LINE UP部分のカード
実際はswiperを使用して、カードがぐるぐる回るようにしているのですが、その実装は「swiperの使い方」などの語句で検索した通りにしているので、詳しい説明は省きます。ここでは、ひとつひとつのカードの実装について備忘録を書いておきます。
実は今回のサイトのこのカード、画像によって縦の長さが微妙に違っています。これは、カード全体のdivで画像用のエリアを確保しただけで、実際のimgでwidth:100%としただけで、heightをきっちり指定しなかったためです。ここはheight:50%とかにするべきでした。さらに、ここでは画像用のエリアをカード全体のdivにbefore要素でpadding-topを指定することで確保していますが、今なら画像用のdivをきちんと親要素の中につくったうえで、そのdivにaspect-ratioを使って画像領域を確保した方がよいのかな、と思います。
カードのHTML
<div class="c-productcard">
<img src="img/brussels-sprouts.jpg" alt="ミニチューリップのアレンジメント">
<p class="c-productcard__text">2月下旬にはチューリップをお届け。お家にひと足早く春がやってきます</p>
<p class="c-productcard__price">※季節限定</p>
</div>
SCSS
.c-productcard{
background-color: var(--color-bg-primary-light);
width:264px;
height: 334px;
box-shadow:0px 3px 6px rgba(0,0,0,0.16);
position:relative; ←imgタグで指定した画像をposition:absoluteで指定するため
ここはrelativeを指定することが必要
display:flex;
flex-direction: column;
&::before{
content:"";
width: 264px;
padding-top:165px; ←幅264px 高さ165pxの画像エリアをつくる
}
img{
position: absolute; ←::before で作成した画像エリアにはめるimgのスタイル設定。
ほんとは幅と縦をきちんと設定しなければならなかった
top:0;
left:0;
object-fit: cover;
}
&__text{
margin:16px;
line-height:1.5;
}
&__price{
font-weight:400;
margin:16px;
margin-top:auto; ←下寄せにするための設定
}
}
Swiperについて参考にしたサイトはこちら
NEWSセクション
NEWS部分は、各項目をクリックすると詳細なお知らせ画面に飛ぶ ということを想定して
<a>タグを実装しました。そのためにセクション全体はtableタグではなく<ul>と<li>タグで作りました。スマホレイアウトでは、日付と項目を縦に配置しています。
HTML
<!-- おしらせセクション 各項目をクリックすると詳細記事に飛べる想定-->
<section class="l-section p-news" id="news" data-aos="fade-up">
<h2 class="c-sectiontitle">NEWS</h2>
<div class="l-inner-wide">
<ul class="p-newscontent p-newscontent__first">
<li class="p-newscontent__date"><a href="#">2023/02/12</a></li>
<li class="p-newscontent__text"><a href="#">ことしもチューリップのお届けが始まりました</a></li>
</ul>
<ul class="p-newscontent">
<li class="p-newscontent__date"><a href="#">2023/01/14</a></li>
<li class="p-newscontent__text"><a href="#">〇〇放送「情報ネットワーク(全国放送)」 で紹介されました</a></li>
</ul>
<ul class="p-newscontent">
<li class="p-newscontent__date"><a href="#">2023/01/01</a></li>
<li class="p-newscontent__text"><a href="#">あけましておめでとうございます</a></li>
</ul>
</div>
</section>
<!-- ---------------------------------- -->
<!-- セクション間のイメージ写真 -->
<div class="u-news-to-faq" data-aos="fade-up">
</div>
<!-- ---------------------------------- -->
SCSS
.p-newscontent{
padding: 25px 0;
border-bottom: 1px solid var(--color-border-gray);
display:flex;
gap:120px;
&__first{
margin-top:90px;
border-top:1px solid var(--color-border-gray);
}
&__date{
font-size:13px;
font-weight:400;
}
&__text{
font-size:16px;
font-weight:400;
}
@include bp.mq{
padding:20px 12px;
flex-direction: column;
align-content: center;
gap:4px;
&__text{
margin-left:20px;
}
}
}
/*セクション間のイメージ写真 NEWSとFAQの間*/
.u-news-to-faq{
width:35vw;
max-width:235px;
aspect-ratio: 3/2; ←はめ込むバラの花の画像にあわせたアスペクト比
background-image:url(../img/grapes-middle.png);
background-size:cover;
background-position:center;
position:relative;
margin-left:auto;
margin-bottom:calc((-70vw / 3 )*0.2);/*計算値通りではないけど、見た目でいい感じに調整*/
z-index:10;
}
NEWSとFAQの間の背景色が変わる部分にまたがる画像は、アスペクト比を画像にあわせたdivを配置し、画像そのものはdivの背景画像として設定しています。
このdivのmarginをマイナスに設定することで、FAQのセクションが画像に(サイトの上部に)はみ出るようにしています。マイナスの値は本来「このdivの高さの半分」なので、今回は35vw*2/3*0.5 だとよかったのかな? でも実際は見た目で調整しました。背景の色よりもこのdivが手前にこなければならないので、divのpositionをrelativeに設定し、z-indexを10として、思い切り手前に設定しています。
FAQセクション
アコーディオンメニューです。
detailタグでとsummaryタグにcssでアニメーションのスタイルをつけて、Jsなしでアコーディオンを実装できないか試してみました。summaryタグにはデフォルトで▼が表示されるのですが、cssでそれを消して、代わりにうっすいアイコンを付けています(色が薄すぎてほとんど見えない!)。
HTML
<!-- FAQセクション detailsタグとsummaryタグでアコーディオンメニュー実装-->
<section class="l-section p-faq" id="faq" data-aos="fade-up">
<h2 class="c-sectiontitle">FAQ</h2>
<div class="l-inner-narrow">
<details class="p-faq__details js-details">
<summary class="p-faq__summary js-summary"><span class="robotfont">Q </span>どんなサービスですか?</summary>
<div class="p-faq__answer js-answer">
<div class="p-faq__ans-inner">
水曜日までにお申込みいただくと、その週末から発送開始。その後は隔週で季節にあわせたお花をお届けいたします。配達のスキップ、停止も随時お受けしており、水曜日までにお申し出いただければ、その週末から配送ストップいたします。
</div>
</div>
</details>
~後略~
SCSS
.p-faq{
padding-bottom: 96px;
}
.p-faq{
&__details{
margin-bottom:20px;
&:nth-of-type(1){
margin-top:60px;
}
}
&__summary{
display:block;//display:list-itemを消して別のものにする。これでデフォのアコーディオン左の△が消える
&::-webkit-details-marker{display:none;}//safariで表示されるアイコンはこれで消せる
padding : 12px 14px;
font-weight:700;
font-size:18px;
background-color:var(--color-bg-primary-light);
cursor:pointer;
transition: 0.2s;
&:hover{
background-color:var(--color-bg-primary-primary);
}
position:relative;
&::after{
position:absolute;
content:"";
top:35%;
right:12px;
display:block;
width:8px;
height:8px;
border-top: 2px solid var(--color-border-gray);
border-right:2px solid var(--color-border-gray);
transform: rotate(135deg);
}
}
&__answer{
overflow: hidden;/*answer部分は二重のdivでかこみ、外側にはpaddingなどは設定するな とのこと*/
}
&__ans-inner{
font-size:16px;
font-weight:400;
padding:12px 8px;
}
}
// アコーディオンが開いているときアイコンを開いた状態のに変えるアニメーション
.p-faq__details[open]{
.p-faq__summary{
&::after{
transform: rotate(-45deg);
transition:0.4s;
}
}
}
SCSSにcssアニメーションを記載して、アコーディオンの開閉をスムーズにできればと思ったのですが、結局うまくいかず、Jsが必要になるということがわかりました。(ゆっくり開くのはできたのですが、ゆっくり閉じることができなかったです。)jsについては下記のページが参考になり、ほぼこのページに書いてあることのコピペですので詳しいコードはここには掲載しません。
ACCESSセクション
PCレイアウトの画面左はtableタグで、右の地図は縦横比を固定したdivを作ってそこにiframeタグでGooglemapを埋め込みました。
他の部分のブレイクポイントは768pxなのですが、このセクションだけブレイクポイントを580pxにしています。改めてScssを見返すと、一か所だけブレイクポイントを380pxにしているところがありますが、多分これ間違いですね(汗)
HTML
<!-- アクセスセクション 表組はPC時は表組み SP時は縦積み-->
<section class="l-section p-access" id="access" data-aos="">
<h2 class="c-sectiontitle">実店舗のご紹介</h2>
<div class="l-inner-wide p-access__inner">
<table class="p-access__info">
<tr>
<th>会社名</th>
<td>フラワーデリバー</td>
</tr>
<tr>
<th>代表者名</th>
<td>〇〇花子</td>
</tr>
<tr>
<th>所在地</th>
<td>長野県茅野市北山×××××</td>
</tr>
<tr>
<th>E-mail</th>
<td>flowerdxx@gmail.com</td>
</tr>
</table>
<div class="p-access__mapwrapper">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d206405.99161148243!2d138.10715327615054!3d36.066820557759904!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x601c4e5d08f6a63d%3A0xf7d929f1922a7056!2z44CSMzkxLTAzMDEg6ZW36YeO55yM6IyF6YeO5biC5YyX5bGx!5e0!3m2!1sja!2sjp!4v1682402821890!5m2!1sja!2sjp"
width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"
referrerpolicy="no-referrer-when-downgrade"></iframe>
</div>
</div>
</section>
<!-- ---------------------------------- -->
SCSS
.p-access{
&__inner{
display:flex;
justify-content: space-between;
margin-top:90px;
@include bp.mq(sl){
flex-direction: column;
align-items: center;
margin-top:40px;
}
}
&__info{
width:calc((100% - 40px) / 2);
@include bp.mq(sm){ ←ここだけブレイクポイントが380pxになっています。たぶん間違い。
width:100%;
}
border-top:1px var(--color-border-gray) solid;
tr{
border-bottom: 1px var(--color-border-gray) solid;
@include bp.mq(sl){
display: block;
}
}
th{
font-size:18px;
font-weight:700;
padding: 20px 10px;
/* 表の中で変に改行しないようにする */
white-space:nowrap;
@include bp.mq(sl){
display: block;
padding:10px 5px;
}
}
td{
font-size:18px;
font-weight:700;
padding: 20px 10px;
/* 表の中で変に改行しないようにする */
white-space:nowrap;
@include bp.mq(sl){
display: block;
padding:10px 15px;
}
}
}
&__mapwrapper{
width:calc((100% - 40px) / 2);
aspect-ratio:4/3;
@include bp.mq(sl){
width:100%;
margin-top:20px;
}
iframe{
width:100%;
height:100%;
object-fit: cover;
}
}
}
CONTACTセクション
お問い合わせフォームです。
フォームの部品(入力ボックスやラジオボタンなど)は標準のものだとカッコわるく、入力欄も狭くて使いづらいので、標準スタイルを無効にして、あらためて設定することが必須です。このあたりのことや「ではどういうスタイルを設定すればよいのか」については、下記の図書がとても参考になりました。
「プロの「引き出し」を増やす HTML+CSS コーディングの教科書」
デザイン的にも優れ、なおかつアクセシビリティにも配慮したコードを実装するにはどうすればよいか、具体例が豊富に書いてあって、とにかく勉強になります。「悪いコードの例」もきちんと解説してあるので、説明は冗長な箇所もありますが、じっくり読むことで「なるほど!」と思わせてくれる解説書。HTMLやCSSの基礎は学習して、ひととおり使えるけど、使いこなせるまでは行っていない、というレベル感の解説書ってあまり他にはないので、とてもおススメです。(「しょーごログ」でもおススメされておりました)
というわけで、ここでのHTMLやSCSSもこの本の解説にほぼ準拠して作成しました。
また、送信ボタンは入力が完了しないと押せないようにし、フォーム自体はGoogleフォームに連携して作成してみました。このへんは「しょーごログ」さんの以下の記事を参考にしました。
HTML
<!-- お問い合わせセクション フォームはGoogleフォームに連携 参考:https://shogo-log.com/google-form-ajax/-->
<section class="l-section p-contact" id="contact" data-aos="fade-up">
<h2 class="c-sectiontitle">お問い合わせ</h2>
<div class="l-inner-narrow">
<p class="p-contact__notice">フォームに送信頂きましたら、<span class="nowrap">折返しメールを差し上げます</span></p>
<div class="p-contact__formwrapper">
<h3 class="p-form__title">お問い合わせメールフォーム</h3>
<!-- Googleフォームに連携させた -->
<form
action="https://docs.google.com/forms/u/0/d/e/1FAIpQLSdOxCRyWc64-zZ_iqPlBrOK1zZRQAxasVC3_wC7nXxI75zrMQ/formResponse"
id="form">
<!-- 問いと答えセットをまとめるコンテナはlabel要素により、フォームとラベルを紐づける-->
<!-- ただしラジオボタンによる回答部分は、回答をグループ化して問いに紐づける必要あり -->
<!-- 問いとこたえをまとめるコンテナ(問い合わせ種類)-->
<div class="p-form__qa p-form__qa-category">
<!-- 問いのdiv legendとid を使ってラジオボタンの複数回答をグループ化したものとまとめて紐づける-->
<div class="p-form__question p-form__question-category" id="categoryGroupLavel">
お問い合わせ種類<span class="u-required">必須</span>
</div>
<!-- ラジオボタン回答 ボタン部分以外も選択可能にするためlabelで囲む-->
<div class="p-form__answer p-form__answer-category">
<ul class="p-form__radiolist" aria-labelledby="categoryGroupLavel">
<!-- aria-labelledby属性は、答えグループと問いを紐づけるためのもの -->
<li><label><input class="radiobtn" type="radio" value="弊社製品について" name="entry.238918848"
checked><span>サービス申込</span></label></li>
<li><label><input class="radiobtn" type="radio" value="いちご狩りについて"
name="entry.238918848"><span>お問い合わせ</span></label></li>
<li><label><input class="radiobtn" type="radio" value="その他のお問い合わせ"
name="entry.238918848"><span>その他</span></label></li>
</ul>
</div>
</div>
<!-- 問いとこたえをまとめるコンテナ(お名前) label要素により、フォームとラベルを紐づける-->
<div class="p-form__qa">
<!-- 問いのdiv -->
<div class="p-form__question">
<label for="name">お名前<span class="u-required">必須</span></label>
</div>
<!-- 回答のdiv 各解答欄にidを設置 -->
<div class="p-form__answer">
<input id="name" type="text" name="entry.1331967290" class="p-form__textbox" placeholder="">
</div>
</div>
~~中略~~
<!-- 問いとこたえをまとめるコンテナ(問い合わせの内容)-->
<div class="p-form__qa p-form__qa-text">
<!-- 問いのdiv -->
<div class="p-form__question">
<label for="message">お問い合わせ内容<span class="u-required">必須</span></label>
</div>
<!-- 回答のdiv 各解答欄にidを設置 -->
<div class="p-form__answer ">
<textarea cols="20" rows="6" id="message" name="entry.1143650844" class="p-form__textarea"
placeholder=""></textarea>
</div>
</div>
<!-- 送信ボタン 入力欄に入力しないかぎりdisabledでボタンが無効化されている。-->
<div class="p-form__submitarea">
<button type="submit" class="p-form__submitbtn js-submitbtn" disabled>送信する</button>
</div><!-- /.submitarea -->
</form>
<!-- 送信失敗メッセージ -->
<p class="u-false-message">送信失敗です</p>
</div><!--/p-contact__formwrapper -->
</div><!--/l-inner-narrow -->
</section>
<!-- ---------------------------------- -->
SCSS
.p-contact{
&__notice{
font-size:18px;
font-weight: 700;
text-align: center;
margin-top:64px;
margin-bottom:48px;
}
&__formwrapper{
background-color:var(--color-bg-primary-light);
padding: 37px 76px;
@include bp.mq{
padding:5vw;
}
}
}
.p-form{
&__title{
font-size: 18px;
font-weight: 700;
text-align: center;
margin-bottom:41px;
}
/*問いとこたえセットをまとめる 768px以下では1カラム*/
&__qa{
display:flex;
align-items:flex-start;
margin-top: 24px;
@include bp.mq{
display:flex;
flex-direction: column;
}
}
/*問いのスタイル*/
&__question{
width:calc((100% - 20px) / 2 );
font-size:16px;
font-weight: 700;
@include bp.mq{
width:calc(100% - 20px);
}
}
/*こたえの領域幅を問いと同じ幅にする*/
&__answer{
width:calc((100% - 20px) / 2 );
@include bp.mq{
width:calc(100% - 20px);
}
}
/*こたえ入力部分のinput要素テキストボックススタイル 入力する文字の大きさにくらべて入力欄の高さに余裕をもたせるため
paddingを設定*/
&__textbox{
/* ブラウザ標準スタイルシートを無効にする */
-webkit-apperance: none;
appearance: none;
display:inline-block;
background-color: var(--color-form-textarea);
box-sizing: border-box;
width:100%;
max-width: 334px;
padding: 10px 20px 8px;
border:none;
border-radius:5px;
font-size:16px;
/*郵便番号の入力部分だけ短い*/
&-postal{
max-width: 158px;
}
@include bp.mq{
width:95%;
}
}
/*textarea要素のスタイル*/
&__textarea{
/* ブラウザ標準スタイルを無効にする (リサイズ無効)*/
-webkit-apperance: none;
appearance: none;
resize:none;
display:inline-block;
background-color: var(--color-form-textarea);
box-sizing: border-box;
width: 100%;
padding: 10px 20px 8px;
border:none;
border-radius:5px;
font-size:16px;
}
/*「必須」ボタンのスタイルはutility.scssで設定*/
}
/*/ フォームエリアの「必須」バッジ */
.u-required{
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
font-size:14px;
font-weight: 700;
background-color:#FBF6E7;
width:50px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 10px;
margin-left: 20px;
margin-bottom:4px;
}
/* ラジオボタンのスタイル */
input[type="radio"]{
/* デフォルトのボタンを非表示にし、本来の配置から切り離す */
opacity:0;
position: absolute;
}
/* ラジオボタンスタイル */
/* 選択肢部分のテキスト配置とクリック範囲の拡張 */
input[type="radio"]+span{
display:inline-block;
position: relative;
font-size:16px;
font-weight: 400;
margin-bottom:18px;
padding-left: 24px;
cursor: pointer;
line-height:1;
}
/* 選択肢部分フォーカス時 */
input[type="radio"]:focus+span{
outline: 1px solid #ccc
}
/* ラジオボタンスタイル */
input[type="radio"]+span::before{
content:"";
position: absolute;
box-sizing:border-box;
top:0;
left:0;
width: 16px;
height: 16px;
border:2px solid #4e301b;
border-radius: 50%;
line-height:1;
}
/* ラジオボタン 未選択 */
input[type="radio"]+span::after{
content:"";
display: none;
}
/* ラジオボタン(選択時) */
input[type="radio"]:checked+span:after{
display: block;
box-sizing: border-box;
position:absolute;
top:0;
left:0;
width: 16px;
height:16px;
background-color:#fff;
border:6px solid #4e301b;
border-radius: 50%;
}
/*送信ボタンまわり ボタンの表示を半透明にするには、:disabled時の設定のcssが必要*/
.p-form{
&__submitarea{
text-align: center;
margin-top: 50px;
}
&__submitbtn{
-webkit-appearance: none;
appearance: none;
width:100%;
max-width:243px;
height:46px;
background-color: var(--color-form-button);
border-radius: 10px;
padding: 13px 0;
font-size:14px;
font-weight: 700;
cursor:pointer;
&:disabled{
background-color:#FBF6E7;
color:#ccc
}
}
}
/*/ フォーム送信NGの時のメッセージを普段は隠しておく */
.u-false-message{
display: none;
}
JavaScript 前述した「しょーごログ」の記事のほぼコピペです。
// フォームの「必須入力」完了ではじめて送信できる仕組と実際の入力内容送信をjQueryで。
// jQ使う時に必須のおまじない↓
$(function() {
//フォーム部分
// 必須項目のinputとtextaresになにか入れないと送信ボタンが押せないようにする(初期値のdisabledが、必須項目を満たすとfalseになって押せるようになるしくみ)
//イベント発効は本来「change」タイミングなのでしょうが、最後のテキストエリアに入力をした瞬間に発効させたほうが使用感がよいので、「input」に変えた
const $submitBtn = $('.js-submitbtn');
$("#form input, #form textarea" ).on('input' , function(){
if(
$('#form #name').val() !== "" &&
$('#form #address').val() !== "" &&
$('#form input[type="email"]').val() !== "" &&
$('#form input[type="tel"]').val() !== "" &&
$('#form textarea').val() !== ""
){
$submitBtn.prop('disabled' , false);
}else{
$submitBtn.prop('disabled' , true);
}
});
//お問い合わせ完了メッセージをページ再読み込みじゃなく(非同期という)JSの機能をつかって出していく→これを非同期でjsで通信=Ajaxと呼んでいるそうです
//#form(送信ボタン)を押すことで、内容(event)を取得し
//GoogleフォームのURLに送信しつつ、ありがとうページ(thanks.html)に遷移して
//送信ボタンそのものは非表示(二回送信することをふせぐため)
$('#form').submit(function(event){
var formData = $('#form').serialize();
$.ajax({
url:"https://docs.google.com/forms/u/0/d/e/1FAIpQLSdOxCRyWc64-zZ_iqPlBrOK1zZRQAxasVC3_wC7nXxI75zrMQ/formResponse",
data: formData,
type: "post",
dataType: "xml",
statusCode: {
0: function(){
$(".end-message").slideDown();
$(".submitbtn").fadeOut();
window.location.href="thanks.html";
},
200 : function(){
$(".false-message").slideDown();
}
}
});
event.preventDefault();
});
// ↓jQ使う時のどあたまに記述する文に対応する閉じカッコ
});
フッター
幅768px以下では、ナビゲーションを縦にならべています。(display:flexとし、flex-directionをcolumnにして実装)
店のロゴ部分はヘッダーのスタイルの使いまわしです。
画面左右に花の画像がある部分は、100vwのdiv要素を設定し、それのbefore・afterにそれぞれ画像を配置してつくりました。どんなウインドウ幅になっても、下位置がコピーライトエリアと接するよう、bottomを0としています。
HTML
<!-- フッターエリア -->
<footer data-aos="fade" data-aos-offset="120">
<!-- フッターナビゲーション部分 -->
<div class="l-footer">
<a class="c-logo c-logo-footer" href="#"></a>
<ul class="l-footer__nav">
<li class="l-footer__navlink"><a href="#feature">ABOUT</a></li>
<li class="l-footer__navlink"><a href="#products">LINEUP</a></li>
<li class="l-footer__navlink"><a href="#news">NEWS</a></li>
<li class="l-footer__navlink"><a href="#faq">FAQ</a></li>
<li class="l-footer__navlink"><a href="#access">ACCESS</a></li>
<li class="l-footer__navlink"><a href="#contact">CONTACT</a></li>
</ul>
</div>
<!-- ---------------------------------- -->
<!-- 一番下のイメージ写真 -->
<div class="l-footer__img"></div>
<!-- コピーライト部分 -->
<div class="l-copyright">
<p class="l-copyright__text">© 2019 FLOWER DELIVER.</p>
</div>
</footer>
SCSS
.l-footer{
background-color: var(--color-bg-primary);
padding-top:200px;
padding-bottom:100px;
display: flex;
flex-direction: column;
align-items: center;
gap:14px;
&__nav{
background-color:rgba(255,255,255,0.6);
display: flex;
gap:24px;
z-index:2;
@include bp.mq{
display:block;
text-align:center;
background-color:transparent;
}
}
}
/*フッター下イメージ写真部分*/
.l-footer{
&__img{
width:100vw;
position:relative;
&::before{
content:"";
display:block;
width:30vw;
max-width:297px;
aspect-ratio: 3/2;
background-image: url(../img/strawberry-middle.png);
background-size: cover;
position:absolute;
left:0;
bottom:0;
}
&::after{
content:"";
display:block;
width:30vw;
max-width:237px;
aspect-ratio: 3/2;
background-image:url(../img/livestock-middle.png);
background-size:cover;
position:absolute;
right:0;
bottom:0;
}
}
}
.l-copyright{
height:60px;
background-color:var(--color-bg-footer-gray);
font-size:12px;
text-align:center;
line-height:60px;
}
まとめ
というわけで、ざっくりですが、しょーごさん演習課題「中級」をベースにしたオリジナルサイトのコーディングの備忘録でした。思いがけず長大な記事になってしまいました。ここまでお読みくださってありがとうございます。
冒頭にも書きましたが、この課題はとても大変でした。「ちょいずらし」で要素が配置されているもの、背景の色にまたがって画像が配置されているところが、特に苦戦しました。
同時に苦労したのがカンプにはあらわれていないけど「ブラウザ幅が中途半端なときの表示をどのようにキレイおとしこむか」というところです。
ブレイクポイントに設定した768pxとか、スマホレイアウトとして仮定した350pxなどの表示はキレイだったとしても、560pxとか、900pxとかで見てみたときに、「あ、タイトルの文字が巨大・・・」とか「えー、この幅だとここの要素が重なってしまうのか・・・」など、こだわるときりがないポイントでした。
今回もすべてを解決することはできなかったのですが、要素の幅やマージン・パディング・フォントの大きさの設定にclampやem、vwなど相対的な値を指定することで、解決できたところもありました。ここはまだまだ自分の学習の余地があるなと思いました。
このブログを読んでくださった方はおわかりのように、私は何かわからないことがあると、その語句で検索してはヒットした、先人のみなさんの書かれた記事を参考にしています。わかりやすいブログを出してくれたり、そもそも独学用のコーディング課題を出してくれたりする先人のみなさんに多大なる感謝をこめて、こちらの記事のまとめとさせていただきます。と、同時に、この備忘録が、どなたかの独学の参考になればとても嬉しいです!
コメント