知識の枝

"All is well"

Recipe pageを作る

約376日前 2020年11月16日0:09
デジタル
HTML devchallenges

改訂履歴


2020/11/16 投稿

1. 背景


この記事はDev Challengesでスキルアップの第四弾です。

今回の課題は料理サイトの作り方ページを作るものです。
課題タイトルは「レシピ ページ」

材料の準備から始まり、調理の手順を解説するページです。
材料を準備したかどうか分かるようにチェックボックスを設置します。

またレスポンシブレイアウトによって、これまでとは少し違ったレイアウト指示を行います。
では始めましょう!

2. チャレンジ内容


・材料と調理方法が記載されたレシピページであること。
・材料があるかどうかをチェックボックスで選択できること。
・何人前か分かること。ケーキの焼き時間が分かること。



3. 成果物の公開方法


Dev Challengesのルールに則り下記①~③の構成とする。

①トップページ
成果物スクショ、デモページへのリンク、経験・学んだこと、何を使用して制作したか

②デモページ
成果物の動作が確認可能なページ

③解説ページ
どのように課題を解決したか説明

①、③は本記事で代用したいと思います。

4. コンテンツ


4.1 - リンク


課題はこちらのサイトから頂いております。
Devchallenges.io

成果物のデモページはこちらです。
デモページ - Recipe page

どのように取り組んだかは4.3項で解説しています。
解説へのショートカット

挑戦課題の元ページはこちらです。
挑戦課題 - Recipe page

4.2 - 概観





この成果物は
「html」と「CSS(bootstrap4.5)」を使用して作られ、
Djangoによってこのホームページに公開されています。

4.3 - 解説


作成したhtmlコードは下記の通りです。
{% load static %}
<!DOCTYPE html>
<html lang="ja">

<head>
<meta charset="utf-8" />
<title>Recipe page</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link rel="shortcut icon" href="{% static 'img/favicon.ico' %}" />
<link href="https://fonts.googleapis.com/css2?family=Montserrat&family=Playfair+Display&display=swap" rel="stylesheet">
<!--
font-family: 'Montserrat', sans-serif;
font-family: 'Playfair Display', serif;
-->
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="{% static 'Recipe_page\recipe_page.css' %}" />
</head>

<body>
<div class="container">
<div class="row">
<div class="col-md-9">
<h2 class="playfair" style="font-weight: 700;">Classic Cheesecake Recipe</h2>
<div>
<img src="{% static 'Recipe_page\6dots.svg' %}" alt="6dots"/>
<h6 class="montserrat" style="padding-left: 20px; margin-top: -20px; font-style: italic;">Look no further for a creamy and ultra smooth classic cheesecake recipe! Paired with a buttery graham cracker crust, no one can deny its simple decadence. For the best results, bake in a water bath.</h6>
</div>
</div>
</div>
<div class="row mb-1 mt-3">
<div class="col">
<img src="{% static 'Recipe_page\photo1.png' %}" class="img-fluid" alt="cake_image" />
</div>
</div>
<div class="row mt-4">
<div class="col-md-3 offset-md-2 order-md-2 mt-3">
<div class="shadow-sm" style="border-radius: 6px;">
<div class="container">
<div class="row">
<div class="col-4 col-md-12 my-3 offset-lg-2 offset-xl-3" style="padding: 0;">
<img src="{% static 'Recipe_page\local_dining-white-18dp.svg' %}" alt="dining" />
<div class="montserrat" style="padding-left: 50px; margin-top: -38px; ">
<h6 style="font-size: 12px; color: #BDBDBD;">YIELDS</h6>
<h6 style="margin-top: -5px; color: #F2994A;">12 servings</h6>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-4 col-md-12 my-3 offset-lg-2 offset-xl-3" style="padding: 0;">
<img src="{% static 'Recipe_page\query_builder-24px.svg' %}" alt="timer" />
<div class="montserrat" style="padding-left: 50px; margin-top: -38px; ">
<h6 style="font-size: 12px; color: #BDBDBD;">PREP TIME</h6>
<h6 style="margin-top: -5px;">45 minutes</h6>
</div>
</div>
<div class="col-4 col-md-12 my-3 offset-lg-2 offset-xl-3" style="padding: 0;">
<img src="{% static 'Recipe_page\query_builder-24px.svg' %}" alt="timer" />
<div class="montserrat" style="padding-left: 50px; margin-top: -38px; ">
<h6 style="font-size: 12px; color: #BDBDBD;">COOK TIME</h6>
<h6 style="margin-top: -5px;">1 hour</h6>
</div>
</div>
<div class="col-4 col-md-12 my-3 offset-lg-2 offset-xl-3" style="padding: 0;">
<img src="{% static 'Recipe_page\query_builder-24px.svg' %}" alt="timer" />
<div class="montserrat" style="padding-left: 50px; margin-top: -38px; ">
<h6 style="font-size: 12px; color: #BDBDBD;">TOTAL TIME</h6>
<h6 style="margin-top: -5px;">7,75 hours</h6>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-7 order-md-1">
<h4 class="playfair">Ingredients</h4>
<h5 class="my-4 playfair" style="font-style: italic;">Graham Cracker Crust</h5>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-1">
<label class="custom-control-label montserrat" for="custom-check-1">1 and 1/2 cups (150g)
<span style="font-weight: 700;">graham cracker crumbs
</span>
(about 10 full sheet graham crackers)</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-2">
<label class="custom-control-label montserrat" for="custom-check-2">5 Tablespoons (70g)
<span style="font-weight: 700;">unsalted butter</span>
, melted</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-3">
<label class="custom-control-label montserrat" for="custom-check-3">1/4 cup (50g)
<span style="font-weight: 700;">granulated sugar</span></label>
</div>
<h5 class="my-4 playfair" style="font-style: italic;">Cheesecake</h5>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-4">
<label class="custom-control-label montserrat" for="custom-check-4">four 8-ounce blocks (904g) full-fat
<span style="font-weight: 700;">cream cheese</span>
, softened to room temperature</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-5">
<label class="custom-control-label montserrat" for="custom-check-5">1 cup (200g)
<span style="font-weight: 700;">granulated sugar</span>
</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-6">
<label class="custom-control-label montserrat" for="custom-check-6">1 cup (240g) full-fat
<span style="font-weight: 700;">sour cream</span>
, at room temperature</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-7">
<label class="custom-control-label montserrat" for="custom-check-7">1 teaspoon
<span style="font-weight: 700;">pure vanilla extract</span>
</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-8">
<label class="custom-control-label montserrat" for="custom-check-8">2 teaspoons
<span style="font-weight: 700;">fresh lemon juice</span>
(optional, but recommended)</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-9">
<label class="custom-control-label montserrat" for="custom-check-9">3 large
<span style="font-weight: 700;">eggs</span>
, at room temperature</label>
</div>
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-10">
<label class="custom-control-label montserrat" for="custom-check-10">topping suggestions:
<span style="font-style: italic;">salted caramel, lemon curd, strawberry topping, chocolate ganache, red wine chocolate ganache, fresh fruit, whipped cream, or raspberry sauce</span>
(recipe in notes)</label>
</div>
<h4 class="my-3 playfair">Instructions</h4>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
1
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;">Adjust the oven rack to the lower-middle position and preheat oven to 350°F (177°C).</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
2
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;"><span style="font-weight: 700;">Make the crust:</span> Using a food processor, pulse the graham crackers into crumbs. Pour into a medium bowl and stir in sugar and melted butter until combined. (You can also pulse it all together in the food processor.) Mixture will be sandy. Press firmly into the bottom and slightly up the sides of a 9-inch or 10-inch springform pan. No need to grease the pan first. I use the bottom of a measuring cup to pack the crust down tightly. Pre-bake for 8 minutes. Remove from the oven and place the hot pan on a large piece of aluminum foil. The foil will wrap around the pan for the water bath in step 4. Allow crust to slightly cool as you prepare the filling.</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
3
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;"><span style="font-weight: 700;">Make the filling:</span> Using a handheld or stand mixer fitted with a paddle attachment, beat the cream cheese and granulated sugar together on medium-high speed in a large bowl until the mixture is smooth and creamy, about 2 minutes. Add the sour cream, vanilla extract, and lemon juice then beat until fully combined. On medium speed, add the eggs one at a time, beating after each addition until just blended. After the final egg is incorporated into the batter, stop mixing. To help prevent the cheesecake from deflating and cracking as it cools, avoid over-mixing the batter as best you can.</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
4
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;"><span style="font-weight: 700;">Prepare the simple water bath (see note)</span> Boil a pot of water. You need 1 inch of water in your roasting pan for the water bath, so make sure you boil enough. I use an entire kettle of hot water. As the water is heating up, wrap the aluminum foil around the springform pan. Pour the cheesecake batter on top of the crust. Use a rubber spatula or spoon to smooth it into an even layer. Place the pan inside of a large roasting pan. Carefully pour the hot water inside of the pan and place in the oven. (Or you can place the roasting pan in the oven first, then pour the hot water in. Whichever is easier for you.)</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
5
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;">Bake cheesecake for 55-70 minutes or until the center is almost set. When it’s done, the center of the cheesecake will slightly wobble if you gently shake the pan. Turn the oven off and open the oven door slightly. Let the cheesecake sit in the oven in the water bath as it cools down for 1 hour. Remove from the oven and water bath, then cool cheesecake completely at room temperature. Then refrigerate the cheesecake for at least 4 hours or overnight.</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
6
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;">Use a knife to loosen the chilled cheesecake from the rim of the springform pan, then remove the rim. Using a clean sharp knife, cut into slices for serving. For neat slices, wipe the knife clean and dip into warm water between each slice.</h6>
</div>
<div class="my-4">
<span class="playfair" style="color: white; font-weight: 700; font-size: 24px; background-color: #F2994A; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.2em; border-radius: 6px;">
7
</span>
<h6 class="montserrat" style="padding-left: 50px; margin-top: -32px;">Serve cheesecake with desired toppings. Cover and store leftover cheesecake in the refrigerator for up to 5 days.</h6>
</div>
<h6 class="my-5 montserrat" style="color: #BDBDBD; font-style: italic;">Source: https://sallysbakingaddition.com/classic-cheesecake/</h6>
</div>
</div>
</div>


<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>

</body>

<footer class="text-center">
<div class="container mt-5">
<p class="text-black">chuna @ DevChallenges.io</p>
</div>
</footer>
</html>

本当はpaddingやmarginもCSSで書いたほうがスッキリすると思うのですが、
途中から書き直すのも手間なので諦めました。
フォントだけCSSで指定することにしました。
.montserrat {
font-family: "Montserrat";
}

.playfair {
font-family: "Playfair Display";
}

フォントはhtmlの<head>の中で読み込ませておいてから、html内で適用させやすいようにCSSでクラス化しています。
下記はフォントの読み込み部分。Google fontsから持ってきています。
<link href="https://fonts.googleapis.com/css2?family=Montserrat&family=Playfair+Display&display=swap" rel="stylesheet">


構成はこんな感じかなと下書きしました。
基本的にこの構成でそのまま作ることができました。



次項以降で詰まった箇所について解説します。

5. 詰まったところ


進める上で困った箇所について紹介します。

5.1 - チェックボックス


下記サイトを参考にして解決しました。分かり易い記事で大変助かりました。ありがとうございます。
Bootstrapでチェックボックスやラジオボタンを実装する

チェックボックスの実装は下記文で可能です。
<div class="custom-control custom-checkbox my-1">
<input type="checkbox" class="custom-control-input" id="custom-check-1">
<label class="custom-control-label" for="custom-check-1">
1 and 1/2 cups (150g)
<span style="font-weight: 700;">
graham cracker crumbs
</span>
(about 10 full sheet graham crackers)
</label>
</div>

こんな感じになります。






適当にクリックしてみると分かると思いますが、
チェックボックスだけでなく、文章部分をクリックしてもチェックが入ります。

チェックボックスの実装方法は以上です。

5.2 - カラムの優先順位


ウェブページを表示する画面のサイズに応じてコンテンツのレイアウトが変わるものを、レスポンシブデザインと呼びます。
例えば、今回の課題ページは
大きな画面では左のカラムに材料や作り方、右のカラムに所要時間が表示されます。



このページを小さな画面で表示した場合、レイアウトが変わり右側にあったカラムが左側にあったカラムの上に表示されます。



このようにコンテンツの並び替えが発生する際、コンテンツの表示順に優先度を設定することで位置関係をコントロール可能です。

優先度は下記コードをコンテンツのクラスに指定することで設定可能です。
order-●●-□□

【●●に入る文字列】
sm, md, lg, xl
●●サイズ以上の画面で優先順位設定を適用

【□□に入る数字】
1, 2, 3, 4, ...
優先順位番号
1が最も優先度が高く、数字が大きいほどコンテンツが後ろに表示されます。

この「order」クラスを指定していない場合、
html上で先に書いたコンテンツが優先されるようになります。

※ちょっとハマった話
コンテンツの表示順序入れ替えについて調べたところ、上記「order」を用いた方法以外に「push, pull」を用いた記述方法が出てきました。

「push, pull」は文字通りコンテンツを「押したり、引いたり」する方法で、やってることは「order」とは異なるのですが結果的に同じような並び替えの効果が得られます。

但し(ここでハマりました)、
「push, pull」が使えるのはBootstrap3までで、Bootstrap4以降は使用できません。
このページに詳細が書いてあります。

したがって、Bootstrap4以降を使用する際は「order」を使って優先順位付けを行いましょう!

5.3 - 文字をずらす


デモページのトップ部分のことです。



アイコンや見出し番号を文章の左側に配置し、文章全体をその右側に並べる場合の方法です。
今回のチャレンジでは上記の冒頭部分と調理手順部分でこの方法を使用しています。

方法は単純で、文章全体を「padding」と「margin」でズラすだけです。
 <div>
<img src="{% static 'Recipe_page\6dots.svg' %}" alt="6dots"/>
<h6 class="montserrat" style="padding-left: 20px; margin-top: -20px; font-style: italic;">Look no further for a creamy and ultra smooth classic cheesecake recipe! Paired with a buttery graham cracker crust, no one can deny its simple decadence. For the best results, bake in a water bath.</h6>
</div>

<img>タグでアイコン画像を読み込ませ、<h6>タグで文章を記述しています。
<h6>タグに対し「style="padding-left: 20px; margin-top: -20px;"」と指定し、文章全体をズラしています。



「padding」はコンテンツ領域内の隙間を操る機能、
「margin」はコンテンツ間の隙間を操る機能を持ちます。

マージンに「-20px」とマイナスの数値を入れることで、隙間を空けるのではなく逆に重ねるといった使い方が可能です。

※他に試してボツになった方法
①グリッドで分ける方法
12本のグリッドのうち、1カラム分をアイコンに割り当て、残りの11カラムを文章に割り当てる方法を取りました。
この方法でもアイコンと文章をズラすことは可能でしたが、ウェブページの画面サイズの変更に伴いカラム自体の幅も大きくなったり小さくなったりする為、アイコンと文章の隙間が一定になりませんでした。
今回は画面サイズに関係無く、隙間を一定に保ちたかった為ボツとしました。

を使用する方法
文章を<span>タグで囲うとアイコンと同じ行に文章を入れることが可能です。
一見これで解決するように思えましたが、文章が長くて改行が生じる場合、改行後の文章がアイコンの真下から始まってしまいました。
文章全体をアイコンより右側にズラしたかった為ボツとしました。

③text-indentを使用する方法
上記②の対策として「text-indent」を採用する方法を試しました。
インデントは文章の始めを字下げすることをいいます。



字下げの大きさは「text-indent: ●●」の●●部分で調整可能です。
また、マイナスの数字を入れることで逆方向に文頭をズラすこともできます。

結果的にインデントの方法では思った通りにならなかったのですが、途中で「padding」と「margin」を使う方法を思いついたので解決しました。
だいぶ遠回りしましたが、色々な方法を試せて面白かったです。

6. さいごに


課題を始める前は「こんなページ自分で作れるのか?」と不安な気持ちもありましたが、完成してみると達成感があります。

できるか分からないけど、きっとできます。
そう思いながら「とりあえずやってみる」という気持ちでこれからも続けようと思います。
みなさんも頑張って下さい!