20200122のHTMLに関する記事は9件です。

p、h1要素の横幅を文字数合わせる

pタグ、h1タグの要素の横幅はデフォルトでは親要素の横幅に合わせられています。

<body>
    <h1>hello world.</h1>
    <p>hello world.</p>
  </body>
h1 {
  background: skyblue;

  /* デフォルトの状態
 display: block */
}

p {
  background: pink;

  /* デフォルトの状態
 display: block */
}

これはpタグ、h1タグはデフォルトのdisplayプロパティの設定がblockとなるためです。

pタグ、h1タグのようなデフォルトのdisplayがblockの要素の横幅を文字数に合わせて設定する場合は以下のようにCSS設定をします。

h1 {
  background: skyblue;

  display: inline-block;

}

p {
  background: pink;

  display: inline-block;
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pre-commitとtextlintを使ってHTMLに潜むゼロ幅スペース文字や記号の表記ゆれを倒す

概要

括弧や数字の全角半角が表記揺れしていたり、href内にゼロ幅スペースが紛れ込んでいてリンク切れが起こってしまったりすることをtextlintを使って防ごうという記事です。

サクッとページ単位で確認できればいい方はこちら

textlintとは?

文章の校正をしてくれるリンターツールです。漢字よりひらがなのほうがいい場合や、「てにをは」がおかしいような文章を指摘してくれます。

導入手順

1. プロジェクトの作成

※ この工程はpackage.jsonを生成するものです。すでにある方はスキップしてください。

npm init

2. パッケージのインストール

npm install --save-dev textlint textlint-rule-prh # textlint関係
npm install --save-dev husky lint-staged # pre-commit関係

3. pre-commitが動作するように設定する

package.jsonに次の項目を追記してください。

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.html": "textlint"
  }
}

4. textlintの設定ファイルを作成

./node_modules/.bin/textlint --init

作成された.textlintrcファイルの中身を次のように上書きしてください。
これでtextlintがHTMLファイルを読むようになり、オリジナルの辞書を利用するようになります。

※今回は使いませんがHTMLを読むためのプラグイン「textlint-plugin-html」については後述します。

{
  "filters": {},
  "rules": {
    "prh": {
      "rulePaths": ["./prh.yml"]
    }
  },
  "plugins": {
    "@textlint/text": {
        "extensions": [".html"]
    }
  }
}

5. 辞書ファイルを作成

package.jsonと同じ階層にprh.ymlというファイルを作成します。
中身を次のように設定してみてください。

version: 1
rules:
  - expected: VS Code
    patterns: VSCode
    prh: 正しい表記はVS Code

  - expected: ""
    patterns: "/[\\u034f\\u200b\\u200c\\u200d\\u200e\\u200f\\u2028\\u2029\\u202a\\u202b\\u202c\\u202d\\u202e\\u2061\\u2062\\u2063\\ufeff]/"
    prh: ゼロ幅スペースを検出しました

項目を増やしたいときは次の塊を追加することで対応できます。patternsには正規表現も利用できますし、リストで複数項目設定することもできます。

  - expected: 正しい表記
    patterns: 検出する表記
    prh: エラーメッセージ(説明文)

参考:prh/prh.yml at master · prh/prh

6. 試してみる

プロジェクト内に適当なHTMLファイルを作成します。たとえば、test.htmlなど。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>私はVSCodeが好きです</p>
<p>ここに→"​"←ゼロ幅スペース文字がいます</p>
</body>
</html>

このHTMLファイルがpackage.jsonと同じ階層にあるとき、次のようなコマンドでリンターに検査させられます。

./node_modules/.bin/textlint test.html

するとおそらく次のようなログがでるはずです。

D:\dummy\dummy\test.html
  10:6  ✓ error  VSCode => VS Code
正しい表記はVS Code           prh
  11:9  ✓ error  ​ =>
ゼロ幅スペースを検出しました  prh

✖ 2 problems (2 errors, 0 warnings)
✓ 2 fixable problems.
Try to run: $ textlint --fix [file]

出ない場合は、node_modulesフォルダを削除し、npm iコマンドを実行してみてください。

7. コミットしてみる

うまくpre-commitが動作していれば次のようなエラーが出てコミットが中断されるはずです。
こちらもうまく出ない場合は、node_modulesフォルダを削除し、npm iコマンドを実行してみてください。

Sourcetree

image.png

TortoiseGit

image.png

いろいろ試してみよう

検出には正規表現も使えるので、他にも様々な表記ゆれや誤実装を回収できそうです。

  - expected: 
    patterns: (
    prh: 全角括弧を利用してください

  - expected: 
    patterns: )
    prh: 全角括弧を利用してください

などなど…。Webサイトの運用で表記ゆれやゼロ幅スペースにお困りの場合は試してみてください。

タグを無視するtextlint-plugin-html

HTMLのタグを無視させたい場合はtextlint-plugin-htmlを一緒にインストールしてください。

npm i -D textlint-plugin-html

.textlintrcの設定は次のようになります。

{
  "filters": {},
  "rules": {
    "prh": {
      "rulePaths": ["./prh.yml"]
    }
  },
  "plugins": [
    "html"
  ]
}

なお、どうやら&copy;などは「©」として解釈されるようなので、不要な実態参照を検出するルールはできない模様。たぶん。おそらく。

検出されない場合がある(追記)

コードの順番など、特定のケースでうまく検出されない場合がある模様。調査中。
https://github.com/textlint-rule/textlint-rule-prh/issues/74

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jQueryのメソッド

jQueryとこの記事について

  • 『jQuery』とは、効果やアニメーションを簡単に実装できるJavaScriptライブラリ。

  •  jQueryを使うとWEBページにアニメーションや効果を簡単につけることができる。

  •  jQueryを勉強中(ど素人)なのですが、復習も兼ねて学んだメソッドを
     下記にメモとして記述していこうと思います。随時更新していきます。

hide

  • セレクタ(HTMLのタグ名やclass名,idなどを指定する)で指定した要素を隠すことができる。

 例: $('h1').hide();

show

  • セレクタで指定した隠れている要素を表示することができる。

 例: $('h1').show(slow);

fadeOut

  • セレクタで指定した要素を徐々に隠すことができる。
  • アニメーションの速度は()内に引数として指定することができる。(1.0秒 → 1000、slowなど)

 例: $('.class').fadeOut(1000);

fadeIn

  • セレクタで指定した要素を徐々に表示ことができる。

 例: $('.class').fadeIn(slow);

slideUp

  • セレクタで指定した要素を下から上にスライドしながら隠すことができる。

 例: $('#id').slideUp(1000);

slideDown

  • セレクタで指定した要素を上から下にスライドしながら表示することができる。

 例: $('#id').slideUp(slow);

css

  • セレクタで指定したCSSを変更することができる。引数①にプロパティ、引数②にプロパティの値を設定する。

 例: $('p').css('color','blue');

 ※ちなみに、
    $('img').css('display','none'); ⇦ hideメソッドと同じ
    $('img').css('display','block'); ⇦ showメソッドと同じ

text

  • セレクタで指定した要素のHTMLの中身を引数で指定した内容に書き換えることができる。

 例: $('p').text('アイウエオ');

html

  • セレクタで指定した要素の中身のHTMLを引数で指定したものに書き換えることができる。

 例: $('p').html('アイウエオ');

find

  • セレクタで指定した要素の子孫要素から、引数で指定した要素を全て取得することができる。

 例: $('.class').find('p');

  この場合、'.class'というクラス内の'p'要素を取得することができる。

children

  • セレクタで指定した要素の子要素(1階層分)から、引数で指定した要素を取得することができる。

 例: $('.class').children('p');

addClass

  • セレクタで指定した要素に引数で指定したクラスを追加することができる。

 例: $('.class1').addClass('.class2');

removeClass

  • セレクタで指定した要素から引数で指定したクラスを取り除くことができる。

 例: $('.class1').removeClass('class2');

hasClass

  • セレクタで指定した要素が引数で指定したクラスを持っているか判定することができる。

 例: $('.class1').hasClass('class2');

 ・if文の条件式として設定することができる
 
   if($('.class1').hasClass('class2'))
   {
     // 処理内容
   }

eq

  • セレクタで指定したオブジェクトから引数で指定した数値と同じインデックス番号をもつ要素を取得することができる。

 例: $('li').eq(2).css('color','red');

index

  • セレクタで指定したオブジェクトにおいて、引数で指定した要素が存在するインデックス番号を取得することができる。

 例: $('li').index($('active'));

prev

  • セレクタで指定したオブジェクトの同じ階層の1つ前の要素を取得することができる。

 例: $('#id').prev().css('color','red');

next

  • セレクタで指定したオブジェクトの同じ階層の1つ次の要素を取得することができる。

 例: $('#id').next().css('color','blue');

attr

  • セレクタで指定した要素に引数で指定した属性名・属性値を設定することができる。
  • また、第2引数を指定しなかった場合、第1引数で指定した属性名の値を取得することができる。

 例: $('h1').attr('id','title');

     var url = $('a').attr('href');

val

  • セレクタで指定した要素のvalue値を取得することができる。

 例: var text = $('#input').val();

animate

  • セレクタで指定した要素に対して、引数1で指定したプロパティの値を設定することができる。
  • また、引数2でアニメーションの速度を指定することができる。

 例: $('h1').animate({'font-size':'20px'},1000)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML + JavaScript 非同期でIPアドレスを取得して表示する

ちょっとクライアントでIPアドレスを取得する必要があったので、
やり方を残しておきます。

今回はipinfo.ioのJSONP API使用してIPアドレスを取得しました。
こちらはchromeのデベロッパーツールでも簡単に試せます。

ちなみにipinfo.ioは自分のIPアドレスを教えてくれるWebサービスです。

JavaScript

$.ajax({
    url: "https://ipinfo.io",
    dataType: "jsonp",
    success: function(res){
         $(".ip-address").text(res.ip);
    }
});

chromeのデベロッパーツールのConsoleに、↑をそのまま貼り付けて実行してもらうと
どういった値が取得できるのか確認できます。

HTML

<p>
    あなたのIPは<a class="ip-address"></a>です。
</p>

画面に表示させるためにデベロッパーツールのElementsにこちらを追加し、
もう一度Consoleでさっきのスクリプトを実行するとIPアドレスが表示できると思います。

まとめ

通常、IPアドレスはサーバで取得することが多いかと思いますが、
今回のようにクライアントでもIPアドレスを取得したい時に役立ちます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【備忘録】Bootstrap

目的

Bootstrap で web page を作る際に調べた内容の備忘録。
作成した web page はこちら(建設中...)。

備忘録

ボタンを押すとページ内の該当箇所にジャンプするアレ

Scrollspy でできる。以下の資料を参照。
https://www.w3schools.com/bootstrap4/bootstrap_scrollspy.asp

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSS3のみでハンバーガーメニューを作る方法

CSSだけでハンバーガーメニューを作れたので参考サイトと作り方をメモします。

参考サイト
https://www.nxworld.net/tips/12-css-hamburger-menu-active-effect.html

  1. リストを作る
<div id="ham-menu">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
  </ul>
</div>

2.CSSをいじくる

#ham-menu{
  position: fixed;  
  height:100%;
  width: 300px;
  right: -300px;
  top: 0;
  background-color: #222;
  padding: 10px 40px;
  z-index: 999;
  box-sizing: border-box;  /*パディングとボーダーを幅と高さに含める*/
  taransition: transform .3s linear 0s;
  }


#ham-nenu:before{
  position: absolute;
  width:50px;
  height: 50px;
  top: 0;
  right: 100%;
  content: "≡";
  text-align: center;
  font-size: 50px;
  color: #FFF;  
  line-height: 50px; /*縦位置中央化*/
  background-color: #222;
  z-index: 999;
  border-radius: 0 0 0 10px;
  display: block;
}


#menu-background{
  background-color: #222;
  display: block;
  height: 100%;
  opacity: 0;
  position: fixed;
  right: 0;
  top: 0;
  transition: all .3s liner 0s;
  z-index: 999;
}

#ham-menu:hover{
  transform: translate(-300px);
}


#ham-menu:hover + #menu-background{
  opacity: .5s;
  z-index: 999;
}


li{
  list-style: none;
  padding: .5em 0;
}


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTMLに​などの特殊空白文字が含まれていないか検品する

Gitのpre-commitでしっかり検査したい方はこちら

ブックマークレット

javascript:!function(){const o=(o=>{const e=[];for(const o of[11,847,8203,8204,8205,8206,8207,8232,8233,8234,8235,8236,8237,8238,8289,8290,8291,65279])e.push(String.fromCharCode(o));return e})(),e=[],t=[],n=o=>{let e=o.parentNode,t=0;for(;e;)e=e.parentNode,t++;return t};for(const o of[...document.all]){const t=n(o);e[t]||(e[t]=[]),e[t].push(o)}e.reverse();for(const n of e)if(n&&n[Symbol.iterator])for(const e of n)for(const n of o)if(-1!==e.outerHTML.indexOf(n)){const o=document.createElement("div");let r=null;e.style.backgroundColor="tomato",e.style.outline="2px solid tomato",o.innerHTML=e.outerHTML.replace(new RegExp(n,"g"),""),r=o.firstElementChild,e.replaceWith(r),t.push([r,e])}if(t.length){console.group("★の位置に特殊文字を検出しました");for(const{0:e,1:n}of t){let{outerHTML:t}=n;e.replaceWith(n);for(const e of o)t=t.replace(new RegExp(e,"g"),"");console.log(n,t)}return console.groupEnd(),void window.alert(`${t.length}個の要素に特殊空白文字が含まれているようです`)}window.alert("OK")}();

概要

Microsoft製品(だけではないけれども)を利用していると、原稿に特殊な目に見えない空白文字が紛れ込むことがあります。

代表格が文字コード8203のゼロ幅スペースです。一見すると何も入力されていないように見えるますが、実際には目に見えない空白文字が入力されています。

これがURLの中に紛れていたりすると非常に厄介です。URLエンコードされてしっかり文字列として解釈されるので、正しくリンクが繋がりません。目視ではこの特殊文字がいないように見えるので、原因に気づくまでに時間がかかってしまうかもしれないですね。

console.log('abc'.length); // > 3
console.log('a'.charCodeAt(0)); // > 97
console.log(String.fromCharCode(97)); // > "a"
console.log(String.fromCharCode(97).length); // > 1

console.log(String.fromCharCode(8203)); // > "​"
console.log(String.fromCharCode(8203).length); // > 1

&#8203;はエディタ上で視認できませんでした。ただ、「?」と表記されることもあるようです。
※ VS Code、Sublime Text3では確認できませんでした。

空白文字は意外と種類がある

NeqZ8y5◆mmft4k9vgtL6さんの公開している5chってどうよ?内、「2. スペースは" "だけじゃない的な話」によると、50種類以上もスペースに似た何かがあるようです。

このブックマークレットは、当該記事で紹介されている空白文字をページ内から検出するものです。

アラートダイアログで結果を表示し、コンソールに詳細を出力します。

おまけで元コード

void function () {
    // 検査する文字列
    const strSet = (charCodeSet => {
        const set = [];

        for (const charCode of charCodeSet) {
            set.push(String.fromCharCode(charCode));
        }

        return set;
    })([
        // 引用:http://anti.rosx.net/etc/memo/002_space.html
        11, // 垂直タブ
        847, // 結合書記素接合子
        8203, // ゼロ幅スペース
        8204, // ゼロ幅非接合子
        8205, // ゼロ幅接合子
        8206, // 記述方向制御(左から右へ)
        8207, // 記述方向制御(右から左へ)
        8232, // 行区切り文字
        8233, // 段落区切り文字
        8234, // LRE
        8235, // RLE
        8236, // PDF
        8237, // LRO
        8238, // RLO
        8289, // 関数適用
        8290, // 不可視の乗算記号
        8291, // 不可視の区切り文字
        65279 // ゼロ幅のノーブレークスペース
    ]);
    const targets = []; // すべての要素が親要素の多い順(ネストの深い順)に格納される
    const cache = []; // もともとのマークアップをキャッシュする
    const getParentLength = node => {
        let parent = node.parentNode;
        let count = 0;

        while (parent) {
            parent = parent.parentNode;
            count++;
        }

        return count;
    };

    for (const node of [...document.all]) {
        const length = getParentLength(node);

        if (!targets[length]) {
            targets[length] = [];
        }

        targets[length].push(node);
    }

    // 親の数が多い順
    targets.reverse();

    for (const layer of targets) {
        if (!layer || !layer[Symbol.iterator]) continue;

        for (const node of layer) {
            for (const str of strSet) {
                if (node.outerHTML.indexOf(str) === -1) continue;

                {
                    const dummyContainer = document.createElement('div');
                    let firstElementChild = null;

                    node.style.backgroundColor = 'tomato';
                    node.style.outline = '2px solid tomato';
                    dummyContainer.innerHTML = node.outerHTML.replace(
                        new RegExp(str, 'g'),
                        ''
                    );
                    // 一次置き換え後の要素のアドレスを確保しておく
                    firstElementChild = dummyContainer.firstElementChild;

                    // 上位階層が多重検出されないように
                    // いったん特殊文字を削除したマークアップに置き換える
                    node.replaceWith(firstElementChild);
                    cache.push([
                        firstElementChild,
                        node
                    ]);
                }
            }
        }
    }

    if (cache.length) {
        console.group('★の位置に特殊文字を検出しました');

        for (const {0: dummy, 1: origin} of cache) {
            let {outerHTML} = origin;

            dummy.replaceWith(origin);

            for (const str of strSet) {
                outerHTML = outerHTML.replace(new RegExp(str, 'g'), '');
            }

            console.log(origin, outerHTML);
        }

        console.groupEnd();
        window.alert(`${cache.length}個の要素に特殊空白文字が含まれているようです`);

        return;
    }

    window.alert('OK');
}();

出典

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【備忘録】HTML

目的

HTML でものを作っている中で、つまづいた内容についての備忘録。
逐次更新の予定。

備忘録

横並びのメニューバーをヘッダ部分につくりたい

header 部分にリストを作成する。 style でリストを横並びにする。

index.html
<body>
    <header>
        <ul>
            <li><a class="btn_menu" href="contents/profile_en.html" target="main">Profile</a></li>
            <li><a class="btn_menu" href="contents/research_en.html" target="main">Research</a></li>
            <li><a class="btn_menu" href="contents/publication_en.html" target="main">Publication</a></li>
            <li><a class="btn_menu" href="contents/distribution_en.html" target="main">Distribution</a></li>
        </ul>
    </header>
</body>

display: inline-block; のところで横並びを定義してる。

style.css
header{
  z-index: auto;
  height: fit-content;
  width: 100%;
  position: relative;
  top: auto;
  background-color: dodgerblue;
  text-align: center;
  z-index: auto;
}

ul {
  overflow: hidden;
  list-style: none;
  margin: 0 auto;
  z-index: auto;
}

ul li {
  display: inline-block;
  padding: 10px 20px 10px 20px;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

getElementId使用して気になったこと

AngularフレームワークでTypeScript を使用してたときにビルドエラーになってとりあえず調べた結果をまとめる。

エラー内容

以下のコードを書いていた。

<!-- HTML -->
<input type="file" id="recorder">
<audio id="player" controls></audio>
// TypeScript
const recorder = document.getElementById("recorder");
const player = document.getElementById("voice-player");

recorder.addEventListener("change", function(e: Event) {
    const file = e.target.files[0];
    player.src = URL.createObjectURL(file);
});

player.srcでsrcは存在しないというエラー。

原因

playerの型がHTMLElement型になっていた。audioタグだしHTMLAudioElementが返ってくると勝手に思ってしまっていた。

.getElementById()はHTMLElement型で返ってくるので自分でキャストする必要があった。

以下のようにキャストした。

const player = <HTMLAudioElement>document.getElementById("voice-player");

これでビルド通ったけど、キャストする以外に方法はないのだろうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む