Webの基本レイアウトまとめとサンプルコード

はじめに

最近,Webレイアウトについて勉強しているので,自分用にまとめてみました.
内容は主に3つです.

  1. 各レイアウトの解説
  2. 各レイアウトを用いたサイト例の紹介
  3. 各レイアウトのサンプルコードの紹介

サンプルコードでは,最近流行りである「Flexbox」を利用してます.
Flexboxについては本ブログでは解説しませんので,最後の参考サイトからご参照ください.


上部ナビゲーション型

画面上部にグローバルナビゲーションを配置し,下部にコンテンツを配置したシンプルなレイアウトです.
f:id:haruka-i1997:20180206133854p:plain
コンテンツを左右いっぱいに表示できるので,コンテンツを大きく見せることができます.
現在,最も普及しているレイアウトの一つですね.

・サイト例
f:id:haruka-i1997:20180206134141p:plain
teno group https://www.teno.co.jp/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>上部ナビゲーション型</title>
    <link rel="stylesheet" href="css/topNavigation.css">
</head>
<body>
    <header class="topNavigation">
       <p>ナビゲーション</p>
    </header>
    <div class="content">
        <p>コンテンツ</p>
    </div>
</body>

topNavigation.css

body{
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}
.topNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.content{
    flex: 1;
    background-color: #eee;
    text-align: center;
    margin-top: 10px;
}


左軸ナビゲーション型

画面左部にグローバルナビゲーションを配置し,右部にコンテンツを配置したレイアウトです.
f:id:haruka-i1997:20180206135947p:plain
ページ数が多いサイトに適しています.
また,常に左部にナビゲーションが配置されているため,ユーザがサイト内で迷子になりにくいメリットがあります.
ナビゲーションの項目数の増加にも対応しやすいレイアウトですね.

・サイト例
f:id:haruka-i1997:20180206140034p:plain
vanguard prague http://vanguardprague.cz/cs

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>左軸ナビゲーション型</title>
   <link rel="stylesheet" href="css/leftNavigation.css">
</head>

<body>
    <header class="leftNavigation">
       <p>ナビゲーション</p>
    </header>
    <div class="content">
        <p>コンテンツ</p>
    </div>
</body>

leftNavigation.css

body{
    display: flex;
    min-height: 100vh;
}
.leftNavigation{
    width: 250px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.content{
    flex: 1;
    background-color: #eee;
    text-align: center;
    margin-left: 10px;
}


逆L字ナビゲーション型

上部ナビゲーション型と左軸ナビゲーション型を組み合わせたレイアウトです.
f:id:haruka-i1997:20180207092048p:plain
ローカルナビゲーションには,バナーや広告を配置することが多いです.
ブログなどでよく見かけるレイアウトです.
このレイアウトの場合は,左軸ナビゲーション型と違い,右側にナビゲーションを配置することもあります.
(当ブログのデザインと同じですね.)

・サイト例
f:id:haruka-i1997:20180206140020p:plain
桶屋 http://studiokeya.com/index.html

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>逆L字ナビゲーション型</title>
    <link rel="stylesheet" href="css/reverseLNavigation.css">
</head>

<body>
    <header class="grovalNavigation">
       <p>グローバルナビゲーション</p>
    </header>
    <main>
        <div class="localNavigation">
            <p>ローカルナビゲーション</p>
        </div>
        <div class="content">
            <p>コンテンツ</p>
        </div>
    </main>
</body>

reverseLNavigation.css

body{
    display: flex;
    flex-direction: column;
}
.grovalNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
main{
    min-height: 100vh;
    display: flex;
    margin-top: 10px;
}
.content{
    flex: 1;
    background-color: #eee;
    text-align: center;
    margin-left: 10px;
}

.localNavigation{
    width: 300px;
    text-align: center;
    background-color: #888;
    color: #fff;
}


シングルカラム

上から順番にヘッダ、グローバルナビゲーション、コンテンツ、ローカルナビゲーション、フッタを配置するレイアウトです.
f:id:haruka-i1997:20180207092234p:plain
目線の誘導を極力減らすことによって、コンテンツの注目度が高まるレイアウトです.
また,タブレットスマートフォンでの表示の際に崩れにくいメリットもありますね.

・サイト例
f:id:haruka-i1997:20180207092320p:plain
KIDORI https://ki-do-ri.jp/

html

<!doctype html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>シングルカラム</title>
    <link rel="stylesheet" href="css/singleColumn.css">
</head>

<body>
    <header class="header">
       <p>ヘッダー</p>
    </header>
    <div class="glovalNavigation">
       <p>グローバルナビゲーション</p>
    </div>
    <div class="content">
        <p>コンテンツ</p>
    </div>
    <div class="localNavigation">
        <p>ローカルナビゲーション</p>
    </div>
    <footer class="footer">
        <p>フッター</p>
    </footer>
</body>

singleColumn.css

body{
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}
.header{
    height: 70px; 
    text-align: center; 
    background-color: #eee;
}
.glovalNavigation{
    height: 70px; 
    text-align: center; 
    background-color: #888;
    color: #fff;
}
.content{
    flex: 1;
    background-color: #eee;
    text-align: center;
    margin: 10px 0 10px 0;
}
.localNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.footer{
    height: 70px;
    text-align: center;
    background-color: #eee;
}


マルチカラム

シングルカラムとは異なり,ローカルナビゲーションの配置をコンテンツと並列にしたレイアウトです.
f:id:haruka-i1997:20180207092938p:plain
主にECサイトやブログなどで幅広く利用されているレイアウトです.
2カラムの構成が一般的です.

・サイト例
f:id:haruka-i1997:20180207093128p:plain
清水寺 http://www.kiyomizudera.or.jp/about/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>マルチカラム</title>
    <link rel="stylesheet" href="css/multiColumn.css">
</head>

<body>
    <header class="header">
       <p>ヘッダー</p>
    </header>
    <div class="glovalNavigation">
       <p>グローバルナビゲーション</p>
    </div>
    <main>
        <div class="content">
            <p>コンテンツ</p>
        </div>
        <div class="localNavigation">
            <p>ローカルナビゲーション</p>
        </div>
    </main>
    <footer class="footer">
        <p>フッター</p>
    </footer>
</body>

multiColumn.css

body{
    display: flex;
    flex-direction: column;
}
.header{
    height: 70px;
    text-align: center;
    background-color: #eee;
}
.glovalNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
main{
    display: flex;
    min-height: 100vh;
    margin: 10px 0 10px 0;
}
.content{
    flex: 1;
    background-color: #eee;
    text-align: center;
    margin-right: 10px;
}
.localNavigation{
    text-align: center;
    background-color: #888;
    color: #fff;
    width: 250px;
}
.footer{
    height: 70px;
    text-align: center;
    background-color: #eee;
}


フルスクリーン

画面いっぱいにコンテンツを配置した大胆なレイアウトです.
f:id:haruka-i1997:20180207093409p:plain
キャンペーンサイトなどで利用されることが多いです.
やはり,コンテンツに目を引きやすいのがメリットとして挙げられますね.

・サイト例
f:id:haruka-i1997:20180207093439p:plain
茶ッカソン https://chackathon.com/

html

<!doctype html>
<html>
<head>
	<meta charset="utf-8"/>
	<title>フルスクリーン</title>
    <link rel="stylesheet" href="css/fullScreen.css">
</head>

<body>
    <div class="content">
        <p>コンテンツ</p>
    </div>
</body>

fullScreen.css

.content{
    width: 100%;
    height: 600px;
    background-color: #eee;
    text-align: center;
}


3分割縦型

左右にナビゲーション、中央にコンテンツを配置したレイアウトです.
f:id:haruka-i1997:20180207093720p:plain
ブログやニュースサイトなどでよく利用されていますね.
情報量の多いページを,すっきり整理して見せることができます.

・サイト例
f:id:haruka-i1997:20180207093907p:plain
KITTE http://jptower-kitte.jp/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>3分割縦型</title>
    <link rel="stylesheet" href="css/threeDivision.css">
</head>

<body>
    <div class="grovalNavigation">
       <p>グローバルナビゲーション</p>
    </div>
    <div class="content">
        <p>コンテンツ</p>
    </div>
    <div class="localNavigation">
        <p>ローカルナビゲーション</p>
    </div>
</body>

threeDivision.css

body{
    min-height: 100vh;
    display: flex;
}
.grovalNavigation{
    flex: 1;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.localNavigation{
    flex: 1;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.content{
    flex: 2;
    text-align: center;
    background-color: #eee;
}


逆U字型

上部にグローバルナビゲーション、左右にローカルナビゲーション、中央にコンテンツを配置したレイアウトです.
f:id:haruka-i1997:20180207094217p:plain
ナビゲーション要素が多いサイトに適しています.
ナビゲーションの項目の増加にも対応できるレイアウトですね.

・サイト例
f:id:haruka-i1997:20180207094241p:plain
quote http://quote-jp.com/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>3分割縦型</title>
    <link rel="stylesheet" href="css/reverseUNavigation.css">
</head>

<body>
    <header class="grovalNavigation">
       <p>グローバルナビゲーション</p>
    </header>
    <main>
        <div class="localNavigation">
            <p>ローカルナビゲーション</p>
        </div>
        <div class="content">
            <p>コンテンツ</p>
        </div>
        <div class="localNavigation">
            <p>ローカルナビゲーション</p>
        </div>
    </main>
</body>

reverseUNavigation.css

body{
    display: flex;
    flex-direction: column;
}
.grovalNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
main{
    display: flex;
    min-height: 100vh;
    margin-top: 10px;
}
.localNavigation{
    flex: 1;
    text-align: center;
    background-color: #888;
    color: #fff;
}
.content{
    flex: 2;
    text-align: center;
    background-color: #eee;
}


グリッドレイアウト

画像をグリッドに沿って配置していくレイアウトです.
f:id:haruka-i1997:20180207094759p:plain
最近おしゃれなサイトでよく見かけますね.
画面全体をすっきりと見せる効果があります.

・サイト例
f:id:haruka-i1997:20180207094832p:plain
P. G. C. D http://www.pgcd.co.jp/#

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>グリッドレイアウト</title>
    <link rel="stylesheet" href="css/gridLayout.css">
</head>

<body>
    <header class="header">
       <p>ヘッダー</p>
    </header>
    <div class="content">
        <div class="image">
            <p>画像</p>
        </div>
        <div class="image">
            <p>画像</p>
        </div>
        <div class="image">
            <p>画像</p>
        </div>
        <div class="image">
            <p>画像</p>
        </div>
    </div>
    <footer class="footer">
        <p>フッター</p>
    </footer>
</body>

gridLayout.css

body{
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}
.header{
    height: 70px;
    text-align: center;
    background-color: #eee;
}
.content{
    margin: 10px 0 10px 0;
    display: flex;
}
.image{
    width: 25%;
    height: 200px;
    background-color: #eee;
    text-align: center;
    margin: 10px;
}
.footer{
    height: 70px;
    text-align: center;
    background-color: #eee;
}


余白多めのレイアウト

コンテンツを大胆に画面の中央などに配置し,余白を広く使ったレイアウトです.
f:id:haruka-i1997:20180207095126p:plain
シングルカラムでよく利用されています.
コンテンツに目が引きやすいメリットがあります.

・サイト例
f:id:haruka-i1997:20180207095216p:plain
CRAZY https://www.crazy.co.jp/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>余白多めのレイアウト</title>
    <link rel="stylesheet" href="css/marginLayout.css">
</head>

<body>
    <main>
        <div class="content">
            <p>コンテンツ</p>
        </div>
    </main>
</body>

marginLayout.css

main{
    display: flex; 
    flex-direction: column; 
    justify-content: center; 
    align-items: center; 
    position: absolute;
    height: 100%;
    width: 100%;
}
.content{
    width: 200px;
    height: 200px;
    text-align: center;
    background-color: #eee;
}


ニュース系情報サイト

これまでのレイアウトの中でも,比較的要素数の多いレイアウトです.
f:id:haruka-i1997:20180207095518p:plain
情報量が多いため、各領域をしっかりと区切ることがポイントです.
コンテンツの領域がはっきりしているため,見やすく使いやすいメリットがあります.

・サイト例
f:id:haruka-i1997:20180207095552p:plain
Yahoo! japan https://www.yahoo.co.jp/

html

<!doctype html>
<html>
<head>
 <meta charset="utf-8"/>
 <title>ニュース系サイト</title>
    <link rel="stylesheet" href="css/newsSite.css">
</head>

<body>
    <header class="header">
       <p>ヘッダー</p>
    </header>
    <div class="glovalNavigation">
       <p>グローバルナビゲーション</p>
    </div>
    <main>
        <div class="localNavigation">
            <p>ローカルナビゲーション</p>
        </div>
        <div class="content-area"></div>
            <div class="content">
                <p>コンテンツ</p>
            </div>
            <div class="content">
                <p>コンテンツ</p>
            </div>
        </div>
        <div class="ad">
            <p>広告</p>
        </div>
    </main>
    <footer class="footer">
        <p>フッター</p>
    </footer>
</body>

newsSite.css

body{
    display: flex;
    flex-direction: column;
}
.header{
    height: 70px;
    text-align: center;
    background-color: #eee;
}
.glovalNavigation{
    height: 70px;
    text-align: center;
    background-color: #888;
    color: #fff;
}
main{
    display: flex;
    min-height: 100vh;
    margin: 10px 0 10px 0;
}
.content-area{
    display: flex;
    flex-wrap: wrap;
}
.content{
    flex: 1;
    height: 200px;
    background-color: #eee;
    text-align: center;
    margin: 0 10px 0 10px;
}
.localNavigation,.ad{
    text-align: center;
    background-color: #888;
    color: #fff;
    width: 250px;
}
.footer{
    height: 70px;
    text-align: center;
    background-color: #eee;
}


商品カテゴリーを選択できるサイドバーや,上部に検索窓を配置するレイアウトです.
各Webサイトのコンセプトに合わせて,コンテンツを配置していきます.
f:id:haruka-i1997:20180207095802p:plain
商品検索機能の使い勝手が良いレイアウトですね.

・サイト例
f:id:haruka-i1997:20180207095830p:plain
ZOZOTOWN http://zozo.jp/

html

<!doctype html>
<html>
<head>
   <meta charset="utf-8"/>
   <title>ECサイト</title>
   <link rel="stylesheet" href="css/ecSite.css">
</head>

<body>
    <header class="header">
       <p>ヘッダー</p>
    </header>
    <main>
        <div class="localNavigation">
            <p>カテゴリ</p>
        </div>
        <div class="content-area">
            <div class="content">
                <p>コンテンツ</p>
            </div>
            <div class="content">
                <p>コンテンツ</p>
            </div>
        </div>
    </main>
    <footer class="footer">
        <p>フッター</p>
    </footer>
</body>

ecSite.css

body{
    display: flex;
    flex-direction: column;
}
.header{
    height: 70px;
    background-color: #eee;
    text-align: center;
}
main{
    display: flex;
    min-height: 100vh;
    margin: 10px 0 10px 0;
    right: 0px;
}
.content-area{
    display: flex;
    flex: 1;
}
.content{
    flex:1;
    height: 200px;
    background-color: #eee;
    text-align: center;
    margin: 0 10px 0 10px;
}
.localNavigation{
    text-align: center;
    background-color: #888;
    color: #fff;
    width: 250px;
}
.footer{
    height: 70px;
    text-align: center;
    background-color: #eee;
}


最後に

今回は,Webレイアウトの基本的な種類をまとめてみました.
Webの種類や情報量などによって、適したレイアウトがあることが分かりました.
個人的には、今回初めてまともにFlexBoxを利用してみて、あまりの便利さに感動しました(゚∀゚)b
今度からもっと使っていきたい.
(サンプルコード間違いがあったらすみません汗)

次からはレイアウトの基本的なルールについてまとめていきたいと思います.


参考書籍&サイト

基本レイアウトについて

知りたいレイアウトデザイン (知りたいデザインシリーズ)

知りたいレイアウトデザイン (知りたいデザインシリーズ)

レイアウトの一覧が分かりやすく,体系的に整理されています.


上記本と殆ど同じ内容ですが、より詳しく解説されています。
参考サイトとかも沢山載ってて非常に分かりやすいです


サイト例について
w-finder.com
muuuuu.org
おしゃれな国内外のサイトを集めたサイトです.
業種やデザイン、色など様々なカテゴリから検索できるので、デザインの参考に非常に役に立ちます.


サンプルコードについて
www.webcreatorbox.com
www.webcreatorbox.com
qiita.com
FlexBoxについて分かりやすくまとめられています.

propellerkitでリストのアコーディオン実装

はじめに

アコーディオンとは、クリックすると隠れていたコンテンツがずる〜っと現れるアレです。
今回はこのアコーディオンを作成していきます。

完成形はこちらです。
f:id:haruka-i1997:20170830151519g:plain


利用するもの

・propellerkit Accordion
 propeller.in

リストデザイン

まずはリストのデザインを見ていきましょう。

以下の記事を参考にさせていただきました。
weboook.blog22.fc2.com


main.html

<div>
  <ul class="menu">
     <li>
        <a>メニュー1</a>
     </li>
     <ul>
         <li><a>メニュー1-A</a></li>
         <li><a>メニュー1-B</a></li>
         <li><a>メニュー1-C</a></li>
     </ul>
     <li>
         <a>メニュー2</a>
     </li>
     <ul>
         <li><a>メニュー2-A</a></li>
         <li><a>メニュー2-B</a></li>
         <li><a>メニュー2-C</a></li>
     </ul>
     <li>
        <a>メニュー3</a>
     </li>
     <ul>
        <li><a>メニュー3-A</a></li>
        <li><a>メニュー3-B</a></li>
        <li><a>メニュー3-C</a></li>
     </ul>
  </ul>
</div>


main.css

.menu {
    width: 500px;
    padding: 0;
    margin: 30px;
}
.menu li {
    overflow: hidden;
    border-bottom: 1px solid #fff;
    cursor: pointer;
}

.menu li a {
    display: block;
    position: relative;
    padding: 0px 10px 0px 50px;
    background: #f2f2f2;
    color: #494949;
    font-size: 14px;
    line-height: 40px;
}

.menu li a:before {
    display: block;
    content: "";
    position: absolute;
    top: 50%;
    left: 25px;
    width: 8px;
    height: 8px;
    margin-top: -4px;
    border-radius: 50%;
    background: #457B9D;
    transition-property:all;
    transition: 0.2s linear;
    color: #494949;
}
.menu li a:hover:before {
    left: -16px;
    width: 50px;
    height: 50px;
    margin-top: -25px;
    transition-property:all;
    transition: 0.2s linear;
    color: #494949;
}


まだアコーディオンは実装していないのでこんな感じです。
クリックしても変化はありません。
f:id:haruka-i1997:20170830153330p:plain


それでは、これからアコーディオンの実装をしていきます。

main.html

<div>
  <ul class="menu">
     <li href="#/main#menu1" data-toggle="collapse">
        <a>メニュー1</a>
     </li>
     <ul id="menu1"class="panel-collapse collapse">
         <li><a>メニュー1-A</a></li>
         <li><a>メニュー1-B</a></li>
         <li><a>メニュー1-C</a></li>
     </ul>
     <li href="#/main#menu2" data-toggle="collapse">
         <a>メニュー2</a>
     </li>
     <ul id="menu2"class="panel-collapse collapse">
         <li><a>メニュー2-A</a></li>
         <li><a>メニュー2-B</a></li>
         <li><a>メニュー2-C</a></li>
     </ul>
     <li href="#/main#menu3" data-toggle="collapse">
        <a>メニュー3</a>
     </li>
     <ul id="menu3"class="panel-collapse collapse">
        <li><a>メニュー3-A</a></li>
        <li><a>メニュー3-B</a></li>
        <li><a>メニュー3-C</a></li>
     </ul>
  </ul>
</div>


大体は上記URLにあるpropellerkitサイトの通りです。
が、説明のため必要でない箇所は極力省いています。


ポイント解説

liタグにある

data-toggle="collapse"

これはアコーディオンコンポーネント
この一文がなければ開閉の動作ができません。

同じくulタグにある

class="panel-collapse collapse"

これもアコーディオンの実装に大切なコードです。
なくても開閉動作はできますが若干挙動がおかしくなります。
安定した動作のためにも書いておく方が良いですね。

ちなみに

class="panel-collapse collapse in"

最後に「in」を入れると、開いた状態が初期状態となります。


liタグにある

href="#/main#menu1"

ここで、親リストをクリックした際に、どの子リストを開閉するのかを決定します。

「#/main」がhtmlのページの名前です。
「#menu1」が子リストの名前です。

子リストの名前は、ulタグにある

id="menu1"

このようにidで指定します。

こうすることで、親リストと子リストが結びつき、
クリックした親リストに結びついている子リストのみが開閉されます。

因みに上記で書いた「#/main」の部分ですが、
これはAngularJSで$routeProviderを使用している時のみ必要となります。

$routeProviderを使用しているときは、
定義しているhtmlの名前をhrefに含めないと
全く違うページに飛ばされてしまう場合があるからです。


さいごに

これでリストのアコーディオン実装は終了です。
ごく基本の形しか書いていないので、色々オプションをつけたいときは上記URLの公式ページで見てください。

以上です。

自作Markdown記法とプレビュー機能の作り方



Markdown記法とは

はてなブログやQiitaなど様々なところで使われている記法です。

Markdown(マークダウン)は、文書を記述するための軽量マークアップ言語のひとつである。本来はプレーンテキスト形式で手軽に書いた文書からHTMLを生成するために開発されたものである。 (wikipedia引用)

例えば、「*タイトル*」と書くと「タイトル」と表示されるような感じです。

今回は、Markdown記法で書かれた文章をhtmlに変換し、
プレビュー機能で文章を表示するところまでを紹介します。



利用するもの

・AngularJS
 プレビュー機能の作成に利用します。
 ※当記事ではAngularJSの知識をある程度持っていることを前提で進めていきます。
 AngularJS — Superheroic JavaScript MVW Framework

・propellerkit
 プレビュー機能の作成に利用します。
 propeller.in




MarkdownをHTMLに変換

今回考えたMarkdown記法は以下の通りです。

Markdown記法 表示結果
#titleタイトル#
タイトル
%red赤い文字% 赤い文字
*bold太い文字* 太い文字
_under下線_ 下線
※あくまで分かりやすさ優先で考えたのでhtmlで書くより面倒なものもあります^^;

さっそくMarkdownで入力された文章をhtmlに変換する処理を作成していきます。
ここでは仮処理として、ボタンが押されたらMarkdownをhtmlに変換するようにします。

ここからAngularJSを利用していきます。

htmlはこちら

<textarea type="text" cols="120" rows="20"ng-model="content"></textarea>
<button type="button" ng-click="convert();"> 変換 </button >


Javascriptはこちら

$scope.content = "";
function convert(){
 var convertContent = $scope.content;
 console.log(convertContent) //変換処理前
 /*変換処理*/
  //タイトル
   convertContent = convertContent.split('#title').join("<div style='font-size:20px;font-weight:bold;'>");
    convertContent = convertContent.split('#').join("</div>");
  //赤い文字
    convertContent = convertContent.split('%red').join("<span style='color:red;'>");
    convertContent = convertContent.split('%').join("</span>");
  //太文字
    convertContent = convertContent.split('*bold').join("<b>");
    convertContent = convertContent.split('*').join("</b>");
  //下線
    convertContent = convertContent.split('_under').join("<u>");
    convertContent = convertContent.split('_').join("</u>");
 
  console.log(convertContent) //変換処理後
}

※AngularJSの基本的な部分は省略しています。


単純なので簡単に説明します。

まず変換ボタンが押されると、「ng-click」にある「convert」関数が動作され、
変換処理がはじまります。

変換処理ではjavascriptの「split」メソッドと「join」メソッドを利用しています。

例えば、入力されたMarkdownの中に「#title」という文字列が含まれていた場合。
まずは「split」メソッドを使って、この文字列を除去します。
次に「join」メソッドを使って、除去した箇所に対応するhtmlを追加します。

このようにすることで、Markdownをhtmlの形に変換することができます。
(だいぶんゴリ押しですが...)

実際にコンソールを使って、変換処理前と変換処理後の文章を比べてみましょう。

例えば、以下のような文章をフォームに入力したとします。

#titleタイトルです#

%red赤い文字です%

*bold太い文字です*

_under下線付きです_


コンソール結果は以下の通りです。

【変換前】

#titleタイトルです#

%red赤い文字です%

*bold太い文字です*

_under下線付きです_

【変換後】

<div style='font-size:20px;font-weight:bold;margin-bottom:-10px;'>タイトルです</div>

<span style='color:red;'>赤い文字です</span>

<b>太い文字です</b>

<u>下線付きです</u>


Markdownの部分がhtmlに変換されていることがわかります。

以上で、Markdownをhtmlに変換する処理が完成しました。
次に、htmlに変換した文章をプレビューで表示する機能を作成していきましょう。



まずはプレビューを表示していきましょう。

上記で仮処理としていた「変換」ボタンを「プレビュー」ボタンに変更し
ボタンが押されたらプレビューのダイアログが表示される機能を作成してきます。

ここでは、propellerkitのModalを利用します。
propeller.in



それでは早速htmlを見ていきましょう。

<textarea type="text" cols="120" rows="20"ng-model="content"></textarea>
<button type="button" data-target="#preview-dialog" data-toggle="modal" ng-click="preview()"> プレビュー </button >
<!--プレビューダイアログ-->
<div tabindex="-1" class="modal fade" id="preview-dialog" aria-hidden="true">
        <div class="modal-dialog modal-lg" >
            <div class="modal-content">
                <div class="modal-header pmd-modal-bordered">
                    <button aria-hidden="true" data-dismiss="modal" class="close"type="button">×</button>
                    <h2 class="pmd-card-title-text">プレビュー</h2>
                </div>
                <p>ここに文章が表示されます</p>
            </div>
        </div>
</div>


ダイアログの表示方法は、上記リンクのpropellerkit公式ページを見ていただいた方が早いかと思います。

実際に「プレビュー」ボタンが押されると、このようなダイアログが表示されます。
f:id:haruka-i1997:20170828145804p:plain


それでは、いよいよhtmlに変換した文章をプレビューで表示していきたいと思います。

htmlは以下の通りです。
1箇所のみ変更しています。

<div tabindex="-1" class="modal fade" id="preview-dialog" aria-hidden="true">
        <div class="modal-dialog modal-lg" >
            <div class="modal-content">
                <div class="modal-header pmd-modal-bordered">
                    <button aria-hidden="true" data-dismiss="modal" class="close"type="button">×</button>
                    <h2 class="pmd-card-title-text">プレビュー</h2>
                </div>
                <p ng-bind-html="previewContent"></p>
            </div>
        </div>
</div>


Javascriptは以下の通りです。
ここも変更点は1箇所のみです。

$scope.content = "";
$scope.previewContent = "";
function preview(){
 var convertContent = $scope.content;
 /*変換処理*/
  //タイトル
   convertContent = convertContent.split('#title').join("<div style='font-size:20px;font-weight:bold;'>");
    convertContent = convertContent.split('#').join("</div>");
  //赤い文字
    convertContent = convertContent.split('%red').join("<span style='color:red;'>");
    convertContent = convertContent.split('%').join("</span>");
  //太文字
    convertContent = convertContent.split('*bold').join("<b>");
    convertContent = convertContent.split('*').join("</b>");
  //下線
    convertContent = convertContent.split('_under').join("<u>");
    convertContent = convertContent.split('_').join("</u>");

   $scope.previewContent= $sce.trustAsHtml(convertContent); 
}


htmlの変更点は

<p ng-bind-html="previewContent"></p>

のみです。
ここでjavascript側で変換したhtmlを反映します。

Javascriptは、最後の

$scope.previewContent= $sce.trustAsHtml(convertContent); 

を追加したのみです。

htmlで「ng-bind-html」を利用する際には、反映したいhtmlを
「$sce.trustAsHtml」を利用してエスケープしてあげる必要があります。
(しなければエラーが出てしまいます)

プレビューの表示結果は以下の通りです。
f:id:haruka-i1997:20170828152459p:plain

無事に表示されました。

しかし、改行や空白がきちんとされていない点が気になります。
ですので、javascriptで以下の処理を追加してみます。

$scope.content = "";
$scope.previewContent = "";
function preview(){
 var convertContent = $scope.content;

 /*改行・空白処理*/
    convertContent = convertContent.replace(/\r?\n/g, "<br>");
    convertContent = convertContent.replace(/\s+$/g,"");

 /*変換処理*/
  //タイトル
   convertContent = convertContent.split('#title').join("<div style='font-size:20px;font-weight:bold;'>");
    convertContent = convertContent.split('#').join("</div>");
  //赤い文字
    convertContent = convertContent.split('%red').join("<span style='color:red;'>");
    convertContent = convertContent.split('%').join("</span>");
  //太文字
    convertContent = convertContent.split('*bold').join("<b>");
    convertContent = convertContent.split('*').join("</b>");
  //下線
    convertContent = convertContent.split('_under').join("<u>");
    convertContent = convertContent.split('_').join("</u>");
    console.log(convertContent)

   $scope.previewContent= $sce.trustAsHtml(convertContent); 
}

改行・空白処理を追加しました。
ここではJavascriptの「replace」メソッドを利用しています。

まず1つめ

convertContent = convertContent.replace(/\r?\n/g, "<br>");

では、改行文字「/\r?\n/g」があれば改行コードに変換しています。

2つめの

convertContent = convertContent.replace(/\s+$/g,"");

では、空白文字「/\s+$/g」があれば空白に変換しています。


コンソールの表示結果は以下の通りです。

<div style='font-size:20px;font-weight:bold;margin-bottom:-10px;'>タイトルです</div><br><br><span style='color:red;'>赤い文字です</span><br><br><b>太い文字です</b><br><br><u>下線付きです</u>

改行している箇所にはしっかりと「br」タグが挿入されていることがわかります。


プレビューでの表示結果は以下の通りです。
f:id:haruka-i1997:20170828154409p:plain

先ほどとは違い、きちんと改行されていることがわかります。

以上でプレビュー機能が完成しました。



おわりに

今回は主にjavascriptのメソッドを使用し、Markdownからhtmlへの変換処理を作成しました。
一度作成してしまえば、少し面倒なhtmlも自作のMarkdown記法でスイスイ書くことができると思います。
ぜひお試しください。

AngularJSでいいねボタン作成


利用するもの


AngularJS
 ボタンクリック時などの各種機能を作る際に利用します。
 ※当記事は、AngularJSをある程度理解していることを前提で書いています。
 AngularJS — Superheroic JavaScript MVW Framework


propellerkit
 いいね数を表示するバッジを作る際に利用します。
 propeller.in 

font awesome icons
 いいねボタンのデザインを作る際に利用します。
 fontawesome.io



ボタンデザイン

 完成形がこちらになります。
 f:id:haruka-i1997:20170827230209p:plain

 早速HTMLを見てみましょう。

<div data-badge=0 class="material-icons pmd-md pmd-badge pmd-badge-overlap">
 <i class="fa fa-thumbs-up fa-lg" aria-hidden="true"></i>
</div>


 単純ですが少し解説してみます。

<i class="fa fa-thumbs-up fa-lg" aria-hidden="true"></i>

 この部分が  にあたります。

<div data-badge=0 class="material-icons pmd-md pmd-badge pmd-badge-overlap">
</div>

 この部分が青色のバッジにあたります。
 バッジをつけたい箇所に囲むかたちで使用します(今回は  ですね)

 「data-badge」の部分でバッジに表示する値を代入します。
 今は仮処理として初期値である「0」を代入しています。

 
 

クリックすると値が増える機能

 例えば
 f:id:haruka-i1997:20170827230209p:plain
 この状態でボタンをクリックすると

  f:id:haruka-i1997:20170827234342p:plain
 こうなる
 要はバッジの数が1つずつ増えていく機能です。

 ここからはAngularJSを利用していきます。
 
 ざざっとコードを見ていきましょう。
 まずはHTMLです。

<div data-badge={{good}} class="material-icons pmd-md pmd-badge pmd-badge-overlap">
<i class="fa fa-thumbs-up fa-lg" aria-hidden="true" ng-click="clickEvalute()"></i>
</div>


 次にJavascriptです。

$scope.good = 0; 
function clickEvalute(){
 $scope.good += 1;
}

 ※AngularJSの基本的なところは省いています。


 こちらも単純ですのでざっくりと解説します。
 
 ポイントは主に2つあります。

 1つ目は「data-badge」の部分です。
 先ほどは仮処理として直接「0」を代入していましたが、これを「{{good}}」におきかえ、
 javascript側で「good」に初期値の「0」をセットしました。
 
 2つ目は「ng-click」の部分です。
 ボタンをクリックするとjavasciptの「clickEvalute」関数が動作し、
 「good」に1が加算されます。
 加算した結果は「data-badge」の部分に反映されます。

 以上で「クリックすると値が増える機能」が完成です。



クリックするとデザインが変わる機能

 例えば
 f:id:haruka-i1997:20170827234342p:plain
 この状態でボタンをクリックすると

  f:id:haruka-i1997:20170828001639p:plain
 色が薄くなります。
 クリックしたかどうかを判別しやすくなります。

 この機能もAngularJSを利用します。

 まずはHTMLです。

<div data-badge={{good}} class="material-icons pmd-md pmd-badge pmd-badge-overlap">
<i class="fa fa-thumbs-up fa-lg" aria-hidden="true" ng-click="clickEvalute()"ng-style="goodStyle"></i>
</div>

 
 次にJavascriptです。

$scope.good = 0; 
$scope.goodStyle = "";
function clickEvalute(){
 $scope.good += 1;
 $scope.goodStyle = {color:'gray'};
}


 変更点は「ng-style」の部分のみです。
 ボタンをクリックして「clickEvalute」関数が動作すると、
 「goodStyle」にクリック後のスタイルが代入されます。
 これが「ng-style」に反映されることで、デザインを変更することができます。 
 
 
 

1度しかクリックできない機能

 一般的な「いいねボタン」は一度に何回もクリックできるものではないので、
 一度クリックすると、その後はバッジの値もデザインも変化しないようにしたいですね。

 色々とやり方はありますが、恐らく一番単純なのがフラグを利用する方法だと思います。

 変更するのはJavascriptのみです。

$scope.good = 0; 
$scope.goodStyle = "";
$scope.goodFlag = false;
function clickEvalute(){
 if(!$scope.goodFlag){
  $scope.good += 1;
  $scope.goodStyle = {color:'gray'};
  $scope.goodFlag = true;
 }
}


 「goodFlag」の初期値をfalseにして、
 「clickEvalute」関数が動作したときに「goodFlag」がfalseならば
 バッジの値とデザインの変更を行います。
 
 最後に、1度クリックした証として「goodFlag」をtrueにすれば
 2度目以降に「clickEvalute」関数が動作したときには、バッジの値やデザインの変更が
 行われない仕組みとなっています。

 
 本当は「ng-disabled」を使った方法を利用したかったのですが、
 調べてみるとbuttonにしか動作しない(?)ようなので、このような方法となりました。


 案外単純で簡潔なコードで作ることができて驚きです。
 ng-styleを使えばもっと色々なデザインが作れそうですね。
 時間があれば他の方法も模索していきたいと思います。
 
 以上です。
 
 

グローバルナビの作り方

こんな感じのやつ

f:id:haruka-i1997:20170717113442p:plain

機能としては

  • クリックしたナビに下線
  • ナビに応じて画面内容も変更
くらいかなあ。
調べてみると色々なやり方があったけど、今回は主にAngularJSのng-styleを使用してみた。
もっと効率の良い方法があると思うので見つけ次第変更していく予定。

 

html

<ul class="globalNav">
  <li ng-click="indexCtrl.method.clickNav(1);"/>
    <a ng-href="./#/introduction" ng-style="indexCtrl.value.style.styleTop">
       <strong>トップ</strong>
       <span>Top</span>
    </a>
  </li>
  <li ng-click="indexCtrl.method.clickNav(2);">
    <a ng-href="./#/main" ng-style="indexCtrl.value.style.styleCourse">
       <strong>コース</strong>
       <span>Course</span>
    </a>
  </li>
  <li ng-click="indexCtrl.method.clickNav(3);" style="margin-left:-5px;">
    <a ng-href="./#/myPage" ng-style="indexCtrl.value.style.styleMyPage">
    <strong>マイページ</strong>
    <span>My Page</span>
    </a>
 </li>
</ul>

クリックしたナビはng-hrefで各画面に遷移できる


javascript

function clickNav(nav){
            if(nav == 1){
                $scope.indexCtrl.value.style.styleTop = {borderBottom:'solid #457B9D'};
                $scope.indexCtrl.value.style.styleCourse = {borderBottom: '#fff'};
                $scope.indexCtrl.value.style.styleMyPage = {borderBottom: '#fff'};
            }else if(nav == 2){
                $scope.indexCtrl.value.style.styleCourse = {borderBottom:'solid #457B9D'};
                $scope.indexCtrl.value.style.styleTop = {borderBottom: '#fff'};
                $scope.indexCtrl.value.style.styleMyPage = {borderBottom: '#fff'};
            }else{
                $scope.indexCtrl.value.style.styleMyPage = {borderBottom:'solid #457B9D'};
                $scope.indexCtrl.value.style.styleTop = {borderBottom: '#fff'};
                $scope.indexCtrl.value.style.styleCourse = {borderBottom: '#fff'};
            }
};

クリックしたナビ番号(仮)をng-clickでjavaScriptに飛ばし、番号に従ってng-styleを設定する。
今回はクリックしたナビに下線を引く処理なので、クリックしたナビには{borderBottom:'solid #457B9D'}のように、下線に色をつけるように設定する。
その他のナビには{borderBottom: '#fff'}で白に初期化する。

まとめると、もっと効率良い方法がある気がしてならん。
時間があったら他の方法も検討していきたい。