20220323のHTMLに関する記事は8件です。

フォームのラジオボタンをカスタマイズ

ラジオボタンのカスタマイズの仕方をいつも忘れてしまうので、自分用にメモ。 HTML <label> <input type="radio" name="性別" value="男性" class="bl_gender"> <span>男性</span> </label> 男性、女性で選択できるラジをボタンを想定。 CSS .bl_gender { display: none; /* 初期のラジオボタンを非表示 */ } .bl_gender + span { /* .bl_genderの次のspan */ position: relative; padding-left: 40px; } .bl_gender + span::before { /* ラジオボタンを作成(外側) */ content: ""; width: 24px; height: 24px; border-radius: 50%; border: 1px solid #969696; background: #fff; position: absolute; top: 50%; left: 0; transform: translateY(-50%); } .bl_gender + span::after { /* ラジオボタンを作成(内側) */ content: ""; width: 12px; height: 12px; background: #006688; border-radius: 50%; position: absolute; top: 50%; left: 6px; transform: translateY(-50%); opacity: 0; /* 基本は非表示 */ } .bl_gender:checked + span::after { /* 選択されたボタンだけ表示 */ opacity: 1; } ↓ こんな感じになります。 bl_genderというクラス名をつけてますが、input[type="radio"]でもいけるとおもいます、たぶん!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Atomで選択したテキストをHTMLタグで囲むコマンドを作りました

Atomで選択したテキストをHTMLタグで囲むコマンドを追加しました。 こんな感じで動作します。 タグで囲みたいテキストを選択し、cmd+ctrl+Tを押すとコマンドが実行され、テキストが<xxx>〜</xxx>で囲まれる(ショートカット設定方法は後述) コマンド実行後、「xxx」が選択された状態になっているので、タグ名を入力する 複数選択も可能です 複数行を選択した場合は、選択されたブロックがタグで囲まれます コマンドの追加方法 Atomのメニューから「Init Script…」を選択してスクリプトファイルを開き、以下のスクリプトを追加します。 encloseTag function encloseTag(){ var editor = atom.workspace.getActiveTextEditor(); var selections = editor.getSelections(); selections.forEach( function(selection){ var text = selection.getText(); var tagged_text; //複数行選択されている場合は改行を追加 if(text.match('\n')){ tagged_text = '<xxx>\n' + text + '</xxx>\n'; } else{ tagged_text = text.replace(/^(\s+)?/, '$1<xxx>') + '</xxx>'; } var options = { 'select': true }; //タグで囲む selection.insertText(tagged_text, options); //インデントを整える selection.autoIndentSelectedRows(); } ); //xxxを選択する var tagname_ranges = []; selections.forEach( function(selection){ editor.scanInBufferRange( /xxx/g, selection.getBufferRange(), function(obj){ tagname_ranges.push(obj.range); } ); selection.clear(); } ); editor.setSelectedBufferRanges(tagname_ranges); } init.jsの最後で、追加したスクリプトをコマンドとして登録します。 atom.commands.add("atom-text-editor", { "EncloseTag": encloseTag }); コマンド追加を反映するため、一度Atomを再起動します。 ショートカットの登録 次に、ショートカットを登録します。(この段階でもコマンドパレット cmd+Shift+P から「EncloseTag」と入力すれば、実行できます。) Atomのメニューから「Keymap...」を選択、「keymap.cson」を開き、以下のコードを追加します。 "atom-text-editor": "cmd-ctrl-t": "EncloseTag" わたしはショートカットの競合がしにくく、比較的押しやすい「cmd+ctrl」のコンビネーションをAtomでは好んで使っています。(「T」はタグの頭文字です) これでコマンドの登録とショートカットキーの登録は完了です。 AtomでHTMLコーディングをされている方のお役に立てれば幸いです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウザ上でフリック入力ができる仮想キーボードを作ってみた

はじめに 先日、対戦型ポケモンWordleをリリースしました。 リリース当初、ただテキストボックスにポケモンの名前を入力する形にしており、入力履歴の管理ができておりませんでした。 入力履歴の機能を追加しようと、大元のWordleを参考に入力用のボタンを用意しようと思いました。 ただ、日本語は50音+濁点・半濁点で80ボタン以上必要で、このボタンからポチポチするのは入力が大変だろうなと思いました。 そこで、ブラウザ上でフリック入力できる仮想キーボードを作ってみました。 完成品 See the Pen フリック入力 by yotty (@yotty) on CodePen. パソコンからでは直接フリック機能が使えません。 パソコンからフリック機能を確認したい方は、デベロッパーツールでデバイスを変更することで試すことができます。 ※Chromeの場合 F12でデベロッパーツールを開き、以下のアイコンからデバイスをモバイル端末に変更 実装 以下、実装内容の解説です。 事前準備 事前準備としてさくっと外観を作っておきます。 また、フリック入力の際、長押しで文字選択されたり、入力のタップでズームされたりしないように以下を追加しておきます。 css body{ user-select: none; -webkit-user-select: none; -ms-user-select: none; -moz-user-select: none; -khtml-user-select: none; touch-action: none; } さらに、フリックした際、濁点・半濁点の切り替えを行った際に入力すべき文字を特定するために以下のような配列を用意しておきます。 const l_word = [ ['ア', 'イ', 'ウ', 'エ', 'オ' ] , ['カ', 'キ', 'ク', 'ケ', 'コ' ] , ['サ', 'シ', 'ス', 'セ', 'ソ' ] , ['タ', 'チ', 'ツ', 'テ', 'ト' ] , ['ナ', 'ニ', 'ヌ', 'ネ', 'ノ' ] , ['ハ', 'ヒ', 'フ', 'ヘ', 'ホ' ] , ['マ', 'ミ', 'ム', 'メ', 'モ' ] , ['ヤ', '', 'ユ', '', 'ヨ' ] , ['ラ', 'リ', 'ル', 'レ', 'ロ' ] , ['ワ', 'ヲ', 'ン', 'ー', '' ] ]; const l_word_switch = [ ['ア', 'ァ'] , ['イ', 'ィ'] , ['ウ', 'ゥ'] , ['エ', 'ェ'] , ['オ', 'ォ'] , ['カ', 'ガ'] , ['キ', 'ギ'] , ['ク', 'グ'] , ['ケ', 'ゲ'] , ['コ', 'ゴ'] , ['サ', 'ザ'] , ['シ', 'ジ'] , ['ス', 'ズ'] , ['セ', 'ゼ'] , ['ソ', 'ゾ'] , ['タ', 'ダ'] , ['チ', 'ヂ'] , ['ツ', 'ッ', 'ヅ'] , ['テ', 'デ'] , ['ト', 'ド'] , ['ハ', 'バ', 'パ'] , ['ヒ', 'ビ', 'ピ'] , ['フ', 'ブ', 'プ'] , ['ヘ', 'ベ', 'ペ'] , ['ホ', 'ボ', 'ポ'] , ['ヤ', 'ャ'] , ['ユ', 'ュ'] , ['ヨ', 'ョ'] ]; フリック入力 フリックを検知するために、「touchstart」「touchmove」「touchend」の3つのイベントを利用します。 「touchstart」で、タッチした場所を記憶しておきます。 その他、フリックしたときのオブジェクトの位置や文字などの設定もしています。 touchstart function onTouchStart(event) { $(event.currentTarget).addClass('gray_for_touch'); position = event.originalEvent.touches[0]; direction = 'c'; //フリックのオブジェクトの位置を移動させておく offset = $(event.currentTarget).offset(); $('.kb_key_u').offset({ top: offset.top - 48, left: offset.left }); $('.kb_key_d').offset({ top: offset.top + 48, left: offset.left }); $('.kb_key_l').offset({ top: offset.top, left: offset.left - 48 }); $('.kb_key_r').offset({ top: offset.top, left: offset.left + 48 }); //テキストセット var l = l_word.find(x => x.includes($(event.currentTarget).text())); $('.kb_key_u').text(l[2]); $('.kb_key_d').text(l[4]); $('.kb_key_l').text(l[1]); $('.kb_key_r').text(l[3]); }; 「touchmove」では、移動した現在の位置を取得して上下左右にどれだけ移動したかを計算します。 上下左右それぞれの移動距離のmaxを取って移動方向を検知し、閾値20を超えたらその移動方向にフリックしたと判定させています。 touchmove function onTouchMove(event) { direction = 'c'; $('.kb_key_u').addClass('transparent'); $('.kb_key_d').addClass('transparent'); $('.kb_key_l').addClass('transparent'); $('.kb_key_r').addClass('transparent'); $(event.currentTarget).addClass('gray_for_touch'); $(event.currentTarget).removeClass('transparent'); var new_position = event.originalEvent.touches[0]; var u = position.screenY - new_position.screenY; var d = new_position.screenY - position.screenY; var l = position.screenX - new_position.screenX; var r = new_position.screenX - position.screenX; var max = Math.max(u, d, r, l); if (max < 20) { return; } var input_key = $(event.currentTarget).text(); $(event.currentTarget).removeClass('gray_for_touch'); $(event.currentTarget).addClass('transparent'); if (max == u) { direction = 'u'; $('.kb_key_u').removeClass('transparent'); } else if (max == d) { direction = 'd'; $('.kb_key_d').removeClass('transparent'); } else if (max == l) { direction = 'l'; $('.kb_key_l').removeClass('transparent'); } else if (max == r) { direction = 'r'; $('.kb_key_r').removeClass('transparent'); } }; 「touchend」では、「touchmove」で検知したフリックの方向から入力すべき文字を判断します。 フリックの方向によってindexを変えて、事前に用意した「l_word 」から入力する文字を決定します。 あとは、テキストボックスの値の最後にその文字を付与します。 touchend function onTouchEnd(event) { $('.kb_key_u').addClass('transparent'); $('.kb_key_d').addClass('transparent'); $('.kb_key_l').addClass('transparent'); $('.kb_key_r').addClass('transparent'); $(event.currentTarget).removeClass('gray_for_touch'); $(event.currentTarget).removeClass('transparent'); var input_key = ''; var key = $(event.currentTarget).text(); var l = l_word.find(x => x.includes($(event.currentTarget).text())); var index = 0; if (direction == 'c') { index = 0; } else if (direction == 'u') { index = 2; } else if (direction == 'd') { index = 4; } else if (direction == 'l') { index = 1; } else if (direction == 'r') { index = 3; } var txt = $('#txt').val(); if (l[index] == '') { return; } $('#txt').val(txt + l[index]); }; 濁点・半濁点切り替え テキストボックスに入力されている最後の文字を「l_word_switch」から探し、indexを1ずらして濁点・半濁点を切り替えて文字を取得しています。 濁点・半濁点切り替え function onTouchStart_switch(event) { $(event.currentTarget).addClass('gray_for_touch'); temp_word = $('#txt').val(); targer_word = temp_word.slice(-1); var l_switch = l_word_switch.find(x => x.includes(targer_word)); if (l_switch === undefined) { return; } var index = l_switch.indexOf(targer_word); if (index < 0) { return; } else if (index == l_switch.length - 1) { index = 0; } else { index += 1; } input_key = l_switch[index]; $('#txt').val(temp_word.slice(0, -1) + input_key); }; バックスペース テキストボックスの最後の文字を削除するだけで実装できます。 バックスペース $(document).on('touchstart', '#kb_key_bs', function (event) { $(event.currentTarget).addClass('gray_for_touch'); var temp_txt = $('#txt').val(); $('#txt').val(temp_txt.slice(0, -1)); }); おわりに 実際のアプリでは、今回紹介したフリック入力を組み込み、入力欄を細かく分けることによって入力履歴の管理を実現しています。 アプリが気になった方はこちらから遊ぶことができるので、ぜひ一度触ってみてください! 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Jekyllをdockerで使ってみました

今までVirtualBoxで仮想環境を作り、LAMPなどを構築していました。 仮想化の勉強をしている中でdockerは、VirtualBoxよりも早いと知りました。 そのためMacにdockerをインストールして、環境を作りました。 そして静的なウェブサイトを作るジェネレーターとして関心があったJekyllを、dockerで試してみました。 ちゃんとdockerに、Jekyllがありました。 今回は、下記の記事を参考にしました。 環境を作る中で、備忘録で書き加えます。 指定のディレクトリを作るときは、親フォルダの下に mkdir -p ./app/_site/ と作ると一度にディレクトリを作ることが出来ます。 私は、htmlappとして、親フォルダを作りました。 このフォルダの中に、docker-compose.ymlを作りました。 ディレクトリは、このような形になります。 これから変換する拡張子mdファイルは、 ./app/_site/ に配置しましょう。 先に docker-compose up を実行してから、変換したいファイルを配置しましょう。 感想 Jekyllを使うための環境を作らなくても良いので、手軽にJekyllを使うことができると思いました。 静的なサイトを作る案件が出たときに、このコンテナーを実行して生産性の向上を図りたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTMLブラウザエンジンの行く末とWeb4について思うことDX

(2022/3/27) 日本のWebサイトで、Firefoxをサポートしないところが増えてきている。 日本だけに関して言えば、自分の予測よりも状況が悪くなっている。Firefox使いとしては由々しき事態である。Webサービスは(IEみたいな終わるブラウザ以外の)あらゆるブラウザで使えるべきだと、開発者の意識を変えていく必要があるのは間違いないが、これも一国の話であり、これで世界の情勢が変わるわけでは無かろう。よって記事の方向性に変更は無し。 TL;DR WebブラウザエンジンはChromiumと、Chromiumを取り込んで動作がほぼ同じになったGeckoの2つになる WebデータはHTMLだけではなく、情報種別に応じたプロトコルでやり取りするようになる Webブラウザはそれらのデータを縫合するインターフェイスになる 一部のやり取りはブラウザではなくネイティブアプリを通して通信するようになる ブラウザの多様性よりも、コンテンツファイルの多様性の方が問題だ Chromiumというバベルの塔と、唯一言語HTML 「バベルの塔」の寓話 (?) はみなさんご存じのはずだ。人間が天まで届く塔を作ろうとしたので、神様が人々の言語をバラバラにしてしまったというお話だ。 ここで私が興味を惹かれるのは、無謀ともいえる高さの建造物ではなく、塔を建設しようとした結果人々の言葉が分化してしまったことだ。そしてこのことはある「言語」を思い起こさせる―HTMLだ。そしてその破滅はChromiumというHTMLブラウザエンジンによってもたらされるだろうと私は考えている。 2022年現在のブラウザシェア ではなぜ「Chromiumとかけまして、バベルの塔とときます」となるのか。それは HTMLブラウザシェアの大半がChromiumベースだからだ。というと馬鹿っぽいので、HTMLブラウザの現状を軽くおさらいする。 まずはこの表を見てほしい。これはStatcounter (SC) が計測したHTMLブラウザの2022年2月時点のシェアを表している。サムネイルでかろうじて読み取れるかもしれないが、Chromeが6割強、ChromiumベースのEdge・Sumsung Internet・Operaも合算すると7割程度という圧倒的なシェアである。その次にあるのがSafari (WebKit) が2割弱、大きく差を空けられてFirefox (Gecko) が4%強という順だ。SCのデータを合計しても100%にならないが、残りはユーザーエージェントなどのブラウザが判別できる情報を秘匿している、ないしブラウザを特定できるデータを取得できなかったと考えるのが妥当だろう。 まだまだChromiumのシェアは統一レベルではない。歴史で例えるなら織田信長の最期の支配圏程度だ。しかし、やがては他のブラウザも飲み込んでもおかしくない、という感じである。 最初の脱落者は ブラウザシェアを見ると、「ぎりぎり三国志だな」と思うかもしれないが、この数字にはからくりがある。WebKitだ。iOS (iPhoneやiPad) でHTMLブラウザをリリースするにはWebKitを使わなくてはならず、結果的にどのブラウザを使っても中身はSafariと五十歩百歩である。そのことを知っている人は (データ連携目的以外で) Safari以外のブラウザを使う理由が無く、一般人も「iOSの標準だから」とSafariを使っているのが現状である。 2022年2月時点では、SCによるSafariのモバイル (スマフォ、タブレット) シェアは26%だ。これは、スマフォ全体のApple (iPhone) シェア (2021年第4四半期で22%) と大体一致する (ただ、SCのスマフォのブラウザシェアを見る限りSCはSafariを過大評価気味な気がする。スマフォを持っているけど、アプリしか使わない層が一定数いるのか) 。 当然ブラウザエンジンの制限に関しては開発者側から猛烈な反発を受けており、イギリスの公正取引委員会にあたるUK Competition and Markets Authorityが調査を進めている次第だ。Appleによるとプライバシーとセキュリティの問題からそうしていると言っているが、専門家からの異論が出ている。最悪の場合、UKでのiPhone販売差し止めなどの事態が起こるかもしれない。そんなことになったら他の国にも飛び火するだろう。iOSのブラウザエンジンに関して、オープン化するかという判断がAppleに求められている。 さて、iOSでのWebKit独占が終わったらどうなるだろうか。まず、デスクトップでSafari以外のブラウザを使っていた開発者が一斉に自分がPCやMacで使っているブラウザを使うようになるだろう。そして、ブラウザ実装の改善もあり「あのブラウザいいらしいよ」とかいう噂が (Twitterなどで) 市井に流れて、他のブラウザを使っている一般ユーザーはそのブラウザを使うようになり、Safariユーザーが少なくなる。もっとも、Safari自体も進歩するのは間違い無いが、ブラウザのリリース頻度があまりにも違い過ぎるので追いつけなくなるだろう (手遅れになる前に更新スケジュールをほかのブラウザ同様月次に切り替えてほしいものだが、現状のAppleの態度を見るにあまり期待できない) 。 Safariのデスクトップシェアが10%なので、MacユーザーにおけるSafari利用率を考慮せずに単純計算するとモバイルのシェアは2~3%程度に落ち込む。実際はここまで落ち込むことは無いだろうから、5%くらいは残るはずだ。ともかく、結果的にWebKit人口が少なくなるので、開発者の関心は他 (というかChromium) に移ってしまう。 ここで、SafariがApple系以外のデバイスに対応していないことが響いてくる (昔あったWindows版Safariのあと、Mac系以外のOSでWebKitを使ったブラウザが登場していない) 。ぶっちゃけ、オープンソースであることを除けば、いつぞやのIEと同じ状況だ。開発の熱量もChromiumやGeckoに比べて冷めているように思われる。iOSのネイティブアプリのお知らせ欄などの表示に使われるだろうからWebKitが完全に死滅することは無い (EdgeHTMLのサポートは引き続き行われるという宣言と同じ理屈) だろうが、高度なレンダリングやJS対応が不要になるため開発は低調になり、セキュリティ関連のアップデートのみになるだろう。 そのような状況で、Safariはどうなるのか。おそらく旧Edgeと似たような道を辿ることになるだろう。ただ、Chromeとは痛み分け同然で別分かれたので、Chromiumを素直に導入するとは考えづらい。GoogleとMicrosoftへの当てつけとばかりにGeckoベースに移行する (と同時に、Mozillaに多額出資する) のではと予想している。素人考えだが、5年後までにはそうなっていそうな気がする (もっと早いかもしれない) 。 (2022/3/25追記) @asip2k25 さんのご指摘で、このシナリオの致命的な問題点が発覚した。 WebKitはC++で作られているが、ServoはRust製だということだ。これではSafariにServo導入は難しい。Safariを捨ててしまうのはAppleブランド的にも良くないと考えたため、持続させる方法として浮かんだ意見だが、リサーチが甘かった。EdgeHTMLと違ってオープンソースというのもあるので、WebKitのコードベースを切り捨てるのは開発者からの不興も買うし、一方でSafari = 旧式というレッテルを張られるのはスタイリッシュさが売りのAppleとしては心苦しいだろうし、板挟みだ。 (2022/3/27) 最悪の状況を打開するには、Safariも再びMac以外で使えるようにすべきだ。そのための下地、つまりWebKitの他OSへの移植はなされているわけだから。Safariのスマートな操作性はApple製品のイントロダクションとして打ってつけだろうし、iOSでSafariを使っているユーザーには願ったり叶ったりだろう。iOS独占という特権がある以上、AppleにはWebKitに対する危機感があまり見られないように見えるのは自分だけだろうか。AppleはWebKitに対する人的・技術的投資を強める必要がある。 皮肉なことに、自由を求めるが余り多様性が無くなってしまうという未来が見える。 余談―なぜWebKitが独裁状態を続けられたのか 最初のiPhoneが登場して15年、これほどの間iOSのWebブラウザがWebKit独占になっているというのは興味深い。理由としては2つ挙げられるだろう。SafariがiPhoneの使い心地に関わっていることと、開発者以外のブラウザエンジンへの関心の薄さだ。 iPhoneを買う人は、Apple製品の使い心地を気に入って選んでいる。それにSafariが貢献しているのはいくらアンチでも否定できないだろう。これで実際の使い勝手が悪かったら、iPhone離れがもっと顕著になっているはずだ。そんなことは無いし、かく言う私もiPhoneユーザーでね。 後者に関しては、Safari is the new IEによる署名活動がたった80人の賛同で終わっていることから伺えるだろう。みんなにとっては、動きさえすればそれでいいのだ。ユーザーはブラウザの多様性に全く注意を払っていない。このことはこの文章の主題と言えるのでよく覚えておいてほしい。 しかし、今回はお上が動き始めたので、WebKit独裁体制の維持に問題が生じる可能性は高い。 最後の砦、Mozillaの行く末は さて、こうしてブラウザエンジンはChromiumとGeckoの一騎打ちとなる。シェアを考えればGeckoが討ち死にするのは必定に見えるが、私はもっと穏やかな(でももっとショッキングかもしれない)最期を迎えるのではないかと考えている。 実は、FirefoxのJavaScriptエンジンSpiderMonkeyにはすでにChromiumのJSエンジンであるV8の一部が使われている。「そんな馬鹿な」と思うのかもしれないが、実際正規表現のライブラリがそうである。これは2年前のことで、それ以降似たようなことは起こっていないが、「ブラウザの挙動の溝を埋める」ためにまたV8やBlinkの一部を取り込んだとしてもおかしくはない。そうなれば、最終的にはGeckoの中身がほぼChromiumになるかもしれない。 「利益ではなくユーザーのため」になるのなら、そういう方策を取るのもやぶさかでは無かろう。かくしてChromiumはロイコクロリディウムのようにGecko (もはやキメラだ) を乗っ取ってしまう。しかし、Web標準の一角を担うMozillaの意地と矜持もあり、エンジンを完全にChromiumに切り替えるのは最後の手段だろう…HTMLエンジンの乱立が「ユーザーのため」にならないと判断しない限りは。しかし、実装間の差は無視できるほど小さくなっているはずだ。 自分の予想ではここまで7年。2029年 (EdgeのIEモードが提供終了する年。「ネットは広大だわ…」で知られる攻殻機動隊 (漫画版)1 の時代設定。Webのマイルストーンを飾るにはふさわしい年ではないか) にはブラウザ戦争が実質終結していることだろう。 そしてWebブラウザエンジンは誰もいなくなった… Chromiumを除いては。 (2022/3/24更新) …などと格好を付けて言ったものの、Pale Moonという、HTMLレンダリングエンジンにGeckoからフォークしたGoannaを用いたブラウザが存在する。ちなみに、JavaScriptエンジンはFirefoxと同じくSpiderMonkeyを使っている。開発頻度は決して低くないが、ユーザーベースがSCに出てこないし、シェアはものすごく低いのは間違いない。そもそも、古き良きFirefoxとの互換性を重要視しているという、ニッチにニッチを重ねたコンセプトでできているからだ。そのため、ブラウザエンジンの多くが絶滅したときにGoannaは注目を浴びるかもしれないが、彼らの期待に応えるようなことはしないのではないか。もし期待に応えるような気概があれば、今頃は一般ユーザーにもっと認知されているはずだ。おそらく、Pale Moonが趨勢をひっくり返すことは起こらない。 (2022/3/27) また、@uasi さんに教えていただいたことだが、ekioh社がFlowというブラウザを開発している。ただ、同名のJavaScriptの静的型チェックツールがあるのでややこしい。kikの一件みたいにならなければよいのだが。こちらのHTMLエンジンは独自製であり(JSはSpiderMonkey)、Raspberry Pi向けのプレビューを配布している段階である。ブラウザ多様性における地位を作り上げることを期待したい。 新しいブラウザエンジンは生まれるか ここまで既存のブラウザエンジンがどうなるかを見ていったが、それでは新参者ニューカマーが現れる可能性はあるのか? 結論から言えば、実質不可能だと思う。 まず、ブラウザに求められる機能があまりにも多岐に渡るようになった。HTML5が発表されてからHTMLはかつて無いほどのマルチメディアプラットフォームになった。音声や動画が再生できるのはおろか、ゲームすら組み立てられる万能さである。それらに求められる機能を少人数で実装するのは無理だ。テキストブラウザが関の山だろう2。WebがDIYできる時代はとっくに終わっているのだ。 仮にゼロベースで開発されたブラウザが完成したとしよう。でもそれを誰が使う? よほどのことが無い限り、パンドラの箱を開けたがる開発者はいないだろう。ChromeはGoogle、SafariはApple、IE (とEdge) はMicrosoftという大きなバックボーンがある。独立独歩なFirefoxの祖先はWeb黎明期の寵児だったNetscapeだ。歴史があるから安心して使える。ということは、結局ブラウザ界は出自主義なのだ。ブラウザの多様性と言っている奴は、新規ブラウザの開発を奨励したり、サポートする体制を整備してくれ。 もしブラウザエンジン独占という最悪の事態[誰にとって?]を避けるためには、W3Cが標準ブラウザ実装を作るしかないだろう。技術も予算もモチベーションも持っている機関が他に見当たらないからだ。それも後述のシナリオで出てくる問題を避けるために複数用意する必要があるから、ブラウザの多様性を保全するならW3Cは現状あるすべてのHTMLブラウザエンジンの開発を各所から移管してもらわなければならない。 生まれで差別されるブラウザ界の中で異彩を放っていたのがOperaだった。かつて自前のPrestoエンジンを用いて、タブという概念をブラウザに持ち込んだ (まさに「よほどのこと」!) 革命児だったが、結局大手がタブ機能を追従した時点で命運が尽きた。Chromiumを導入した挙句、没落した現状には目が当てられない。 ここから分かることは一つだ。今や、革新的な機能を実装しようとも大手に真似される。だったらリソースを勝ち馬に当てたほうがいい。もしくは既存のブラウザエンジンを利用して自分のブラウザを作って、先進性を示すほかない。だが今のところ、他のブラウザに影響を与えるほどの新機能を備えたブラウザはOpera以降存在していない。 でも新規HTMLエンジンが登場しないのは問題無いのかもしれない。新EdgeはChromiumを使いながら、Chromeに無い機能を様々に追加している。そしてそれはChromiumの発展にも寄与している。ブラウザの将来を暗示するような展開である。そして先ほども述べたとおり、大多数のユーザーがブラウザを選ぶ基準は「動くかどうか」である。Googleが嫌いだったり、天邪鬼でない限り、Chromeを選ばない理由は無い。 (2022/3/27)そんなことを言っている私はFirefoxユーザーである。IEから移った最初のブラウザだからであり、何となくその操作性を気に入っているから使い続けている。閉じたタブを再度開く際にどこかのタブを右クリックすればいい(Edgeもそう)と、拡張機能を入れなくても(セキュリティ的な都合で、会社のChromeには拡張機能を入れられずしんどい)、検索で大文字小文字を区別できたり、単語単位で検索できる点が気に入っている。 ブラウザ開発で競争する時代はもはや終わった。オープンソースで世界中の開発者の善意を募る方向にブラウザ開発は進化している。 手を取りあってHTMLブラウザを作ろう、ブラウザ開発者よ。 余談―ブラウザ業界とゲーム機業界の比較 三つ巴でシノギを削るゲーム機業界と比較すると、ブラウザの多様性は確かに大事に感じるが、2つ見落としがある。ブラウザはインフラだということと、ブラウザは無料だということだ。 ゲーム機はあくまで嗜好品であり、自らのライフスタイルや好みに合った商品、もしくはソフトのライブラリから選べばいいが、ブラウザには動作の透明性や一貫性が求められる。 ゲーム機によってAボタンが○ボタンでも問題は無いが、ブラウザは<button>がボタンとして描画されないと困る。マリオが遊びたかったらSwitch一択ということに何人たりとも異論を挟まないが、特定のブラウザでしか (では) 開けないページはユーザーから槍玉に上げられる (代替ブラウザが無料でダウンロードできる時代なのに!) 。 また、現在のブラウザは無料が当たり前なので、「安い方を選ぶ」「より表現力のある高級版にする」という選択はできない。そのため、ブラウザ間の競争は、ゲーム機のそれと性格を異にする。 ブラウザ統一の先に しかし、統一したとしても三日天下ということは歴史上茶飯事だ。秦や隋の滅亡、カエサルの暗殺、源氏将軍の断絶、豊臣氏の敗北、国際連盟の失敗…いずれにも共通することは後釜が前任の長所を活かし短所を改め、長続きする体制を築き上げたことだ。統一者は基盤を作ることに長けていても、それを維持する才能には恵まれていないことが多い。両者に必要とされるスキルのベクトルが違うからだ。 このことを考えると、Chromiumがブラウザ界を独占しても、それが長続きするとは到底思えない。かつての歴史に見る通り、インフラ (Googleなどが立ち上げた規格) は残っても、ブラウザは生き残らないのかもしれない。 Chromium覇権樹立後のシナリオ (フィクション) HTMLブラウザはもはやChrome一択となった。対抗馬を失ったChromiumの進化は止まり、Googleが思いついた誰得な新機能ばかりが追加されるようになる。かつてのIEを思わせる殿様商売ぶりに、ユーザーは落胆するだろう。 そして跋扈するのはクラッカー (あえてハッカーとは呼ばない) だ。彼らはChromiumの (主に誰得機能の) 脆弱性を突いて、Webの尊厳を大いに傷つけるだろう。ひょっとしたらオープンソース開発者として潜り込んでいるかもしれない。そしてそのバグフィックスをする間、被害を被るのは一般ユーザーである。エンジンが複数あれば避難ができるのに!3 しかし時すでに遅し。一からブラウザを実装できるものは存在しない。 そんな中人は考える。果たしてHTMLである必要はあるのかと。そもそも通信データがHTMLで、スタイリングがCSSで、スクリプティングがJavaScriptだけというのはおかしくないか? とWeb開発者は自問自答するようになる。 Web4のすがた (真面目な考察) そしてWebはHTMLだけでは無く、例えば商品情報を伝える言語、商取引に特化した言語、動画のメタデータ言語といった具合に、それぞれの機能に特化した言語が開発され、それらを (HTTPS経由で) やり取りするだろう。もはやWebブラウザは単体で完成したアプリではなく、言語パーサーなどの各機能に特化したプラグインの集合体となる (APIが拡張機能に取って代わる) 。通信データをオーガナイズする部分 (htmlにおける<head>) はC言語みたいにヘッダとして独立したファイルになるだろう。そうなればヘッダファイルはまるでいにしえの<frame>ページである4。あるいは通販会社のプロプラエタリなネイティブアプリで取引をする時代になる5のではないか、というのが私の見立てである。 (2022/3/24追記) 早い話、HTMLレンダリングはServo、JavaScriptエンジンはV8みたいに、Pale MoonやFlow以外にもエンジンの系統が違うブラウザが現れてもいいはずだし、各種エンジンはそれに対応すべきだ。むしろマニアがチューンナップしたり (例え自由ソフトウェアのようにソースコードが修正できなくても、ある程度触れる範囲があってもいいはずだ) 、エンジンの一部に問題があっても差し替えられるように、ブラウザだけでなく、エンジンの各種プラグインを選ぶ権利をユーザーが持つべきだ。それこそが真の「ブラウザエンジンの多様性」ではなかろうか。開発がほぼ停止状態だが、AvantやLunascapeのようなブラウザが増えることを願いたい。 そこでは、スタイリングも自分の使いやすいスタイルシートを配信することになり、ロジックはWebAssembly中心で、開発者の心づもりで選ばれたプログラミング言語が使われることだろう。もはやCSSやJavaScriptはOne of themである。現在のスタイル記述言語がCSSの派生しかないことを考えると、CSSは続投するだろう。しかしXAMLみたいにマークアップにスタイルを埋め込むスタイルは復活しそうだ(Atomic CSSという形で段階的に復活してはいる)。Node.jsのおかげでJSが生き残るのは間違い無いが、相対的な立ち位置は後退することが予想される。 このように、各種仕様が細分化されることで、個人開発者が入り込む余地がまたできる。部分最適が進んだり、新規の便利機能を盛り込みやすくなるだろう。どこかでセキュリティ問題が発生すれば、そのモジュールを切り離すことができる。機能ごとに各自がソフトを選んで問題無いことは、npmとyarnの両立によって証明されている。 そして、HTTP (S) の未来は暗くない。通信プロトコルという重要な部分を担っているので普通に生き残るはずだ。通信会社はHTTPに注力しており、他のプロトコルが入り込む隙は無い (SPDYやQUICがそうであったように、新しいプロトコル提案は逆にHTTPに取り込まれる) 。むしろ送信データの分化が進むことで旧来の (非セキュアな) HTTPが廃止されるかもしれない。様々な文書を運ぶことになるため最適化が問題だが、これもHTTP規格の進化と6G通信の確立でさしたる問題ではなくなるはずだ。 Web3というのは現在議論の的 (ブロックチェーンがこれからの通信の核となる可能性はなかなか高いと思う) となっているので、このような未来予想図を私はWeb4 (検索したところ、出てくるのはマイクロソフトの「Expression Web 4」だから、誰もまだ考えていない! ブルーオーシャンだ!) と名付ける。Webの発達速度を見る限り、Web5にはならないだろう。 (2022/3/27)Web4.0なら、色々な人が予想図を立てているので、まだまだ未確定事項は多いが、一つの考え方として受け止めてほしい。 みんなHTML・CSS・JavaScriptを書かない このような未来予測をする理由は、Webブラウザ3種の神器、すなわちHTMLやCSS及びJavaScriptからみんな手を引きたがっているからだ。 HTMLについては、Qiitaで使えるMarkDownがその例だ。 いちいち<p>と書く代わりに文章を書く。 <a href="https://www.yahoo.co.jp">リンク</a>では無く[リンク](https://www.yahoo.co.jp)だ。 MarkDownがお好みでないならHamlやPugなど、代わりはごまんとある。 これも、タグをいちいち書くのは面倒なうえ、プログラミング言語で操作するのが面倒なことは勿論、HTMLの変な仕様を挙げれば切りが無い (新しい要素は比較的まともだが、古い要素は突っ込みどころしかない) からだ (自分のHTMLおよびCSSに対する意見について、詳しくは下の記事を読んでほしい) 。 CSSだって直接書くのではなく、基本的にはSass(SCSS)で書いて変換する。ミックスインやスタイルの継承ができて便利からだ。対抗馬のLESSは名前通りそれほど使われていない(less often used)。ところでStylusを使っている人はいるかい? ただ、CSSの仕様に関しては策定チームが分かれた分効率的になっており、Sassの魅力であるネスト記法を取り入れる動きがあるので、3種の神器の中ではまだ愛されている方かもしれない。 JavaScript6はバグの温床が多いので、TypeScriptを使って型変換をミスらないようにする開発者は多い。そう言えばJavaScriptの体裁とは全く違うCoffeeScriptなんてのもあったよね。 また、ECMAScript仕様書にしか上がっていない先進的な機能や、IE11のような時代に取り残されたブラウザ用にコードをトランスパイルするBabel7というコンパイラが多用されている。ちなみに文章冒頭の例え話との一致は偶然だ。書いていて気付いた。 さらに、Web上で各種プログラミング言語の環境を動かせるようになるWebAssemblyが開発された。この仕様の目的はJSの実行時コンパイルによる速度の低下を避ける (そのためJavaScriptのWebAssemblyというのも存在する) というものだが、このことはWebプログラミングにおけるJavaScriptの絶対性を低下させるということにつながっている。 JavaScriptのプロトタイプベース継承には癖があるが、とりあえずメンバーの名前さえわかればオブジェクトから読み出せるというのは強みだし、他の言語と共存していくはずだ。むしろWebAssemblyが発達したら (Scriptではない) JavaやGoなどがフロントエンドでも重用されるようになり (そうなればJavaとの混同が無視できなくなるので、JavaScriptは開発時のコードネームLiveScriptの名を取り戻すはずだ。ECMAScriptって呼びづらいし) 、むしろJSを他の言語のように改造するのが目的のトランスパイル言語の方がお役御免になるかもしれない。 トランスパイル機能の問題は、それ自身では意味を持たないで、ブラウザが解釈できる形に変換するという点だ。要するに、既存の機能に寄生している (だから原理主義者な私は可能な限りヴァニラなHTML・CSS・JSにこだわる) 。だが、ブラウザがこれらの言語に対応するのであれば、3種の神器はあまり使わなくなるだろう (特にHTML) 。いちいちトランスパイルしなくて済むので、ネットにアップロードするのにかかる時間も減る。 Web3が通信の秘匿と非中央集権化を求めるのであれば、Web4はコンテンツの自由が中心になる。独裁国家 (そういえば、個人の通信を逐一傍受する自由国家がありましたよね?) は認めたがらないだろうが、社会の改良には自由は必須である。 HTMLという恐竜8―本来の目的に立ち返る時 HTMLはCERNという1研究所が文書データを公開するための言語だった。これが類似の技術と異なる点は、他の文書にリンクできることだった。画像や表データなど、ネットで配信されるあらゆるコンテンツを表現できるHTMLはさまざまなデータを意味付け (セマンティック) して整理できるという利点から、インターネットのデファクトスタンダードとなった。ティム・バーナーズ=リー博士のユビキタスな世界を作るという熱意も相まって、インターネットは急速に発展していった。 ブラウザの行く末がプラグインの集合体になるのではないかという話をした際に、Flash Playerを思い出した人も多いだろうが、あれは滅びるべくして滅びた。まずプロプラエタリな製品だったので、技術革新が進まない。そしてさらに致命的なことに、FlashはHTMLにとっては中身の分からないシュレディンガーの猫だったからだ。iPhoneにFlashを載せないことを決断したジョブズさんはHTMLの拡張性を当時の誰よりも理解していたと思う。ブラウザの性能が上がれば、Flashがさまざまな要素をセマンティックに取り込めるように改良されていったHTMLにお株を奪われるのは避けられないことだった。要するにFlashの役目は時間稼ぎだった。 しかし、HTMLがかつてのFlashの領域まで侵食していった代償として、肥大化してしまった。万能すぎたのだ。ブラウザに要求される要素はもはや個人の手に負えない。そんなHTMLがこの先生きのこるにはどうすればよいのか。 それは、元来の目的であった「他のファイルにリンクできる文書用言語」という原点に立ち戻ることである。つまり、単純なリンク付き文書を書くためのHTMLのサブセットを作るのだ。文書間の関係を記述する点、特にアクセシビリティ面での配慮において、HTMLの代替案はいずれも優れていないように思われる。 HTMLの課題として、モジュール化していないということがある。HTML関連技術の最大の弱点は、単一ページしか考えられていないことだと私は思う。<h1>~<h6>という柔軟性を一切持たない見出し機能を見ればわかる通り、HTML仕様はモジュールごとのセマンティックを考慮していない (outline algorithmって結局どうなったんだろう) 。しかし、Web4の進化が起これば、ページの構成部分はすべてレゴブロックみたいなパーツとなる。1ページ全体の論理構造などどうでもよくなるだろう。 そのような未来なら、一般的なニュースなどの文章はHTML (のサブセット) として配信され、HTMLがオールドスピーク (誰も読み解くことができない言語。代替言語たるニュースピークの政治的意図などは置いておく) とならなくても済むだろう。 まとめ 遅かれ早かれWebKitは没落し、GeckoはChromiumとの共存をするために融合していくだろう。ブラウザエンジンは統一されるが、今度はコンテンツファイルの分化が発生するようになる。多くのWebページがMarkDownなどのHTML以外の言語で書かれ、スタイリングはSassなどが直接使われ、ページのスクリプトはWebAssemblyで各種プログラミング言語で書かれるようになる。JavaScriptがインタプリタ実行されることはもはやなくなり、名前もLiveScriptと呼ばれるようになる。 Webブラウザはエンジンが一式を用意するスタイルから、各種機能のエンジンをユーザーが選択できるように変更される。HTMLは今のような万能マークアップ言語ではなく、文章リンクに特化したものに変わっていくはずだ。HTMLでアプリを作る時代は終わりを告げるだろう。 余談―EdgeHTMLはどうすればよかったのか 全くトピックから外れてしまうが、ブラウザ興亡史を考える上では触れなければならないだろう。どうすればEdgeは自前のレンダリングエンジンを捨てずに済んだのだろう? 答えは簡単だ―オープンソースでやればよかった。 Prestoがプロプラエタリなのはまだ分かる。開発された当時はオープンソースなんて概念がまだ浸透しきっていないし、オープンソースと関わりが深い自由ソフトウェアを警戒していたのは企業人としては納得いくところだ。しかし、Edgeが発表された時期は様相が変わる。すでに主だったブラウザはオープンソースが当たり前だった。実質Apple製デバイスでしか使えないWebKitもオープンソースなんだし、ユーザーベースがはるかに大きいWindowsでできないわけが無いだろう。 何よりも解せないのは、Edge公開の前年に当たる2014年に.Net Frameworkの仕様の一部をオープンソース化したことだ。なぜそこまでしておいてEdgeHTMLはソース非公開にしたのだろうか。 (2022/3/25追記)互換性に関する取り組み WebKitのブログに、Working together on Interop 2022という記事が紹介された。Apple、Bocoup、Google、Igalia、Microsoft、MozillaというWeb界をしょって立つ大御所たちが、ブラウザの相互互換性(Interop)に関する取り組みを公開している。 これからのブラウザ界がどのような機能を優先して取り組んでいくかということが事細かに書かれている記事だ。この記事の本題からは外れるが、カスケードレイヤーや、コンテナクエリ―実装につながるContainmentの実装など、期待の大きいHTML・CSS仕様の実現に本腰を入れることが伝わってくる。 このような運動がしっかり機能しているうちは、自分が予想したディストピアは起こらないような、そんな希望を持てた(本当に痛い文章だけれど、自分が考えたことを消してはいけないと思うので、この記事はそのまま残す)。頑張れWebKit、負けるなGecko、最悪の事態は回避してくれ。 単行本が発売された1990年、インターネットは影も形も無かった (映画になった1995年には普及し始めたが、技術的な問題もありまだニッチな未来的サービスだった) 。当時隆盛を誇ったパソコン通信は固定サーバーとの接続だったし、ARPANETは限られた大学や軍事施設でしか使われなかった。そんな時代にあのようなネット社会を描いた士郎正宗先生には兜を脱ぐ。 ↩ 何もテキストブラウザを軽んじているわけではない。むしろアクセシビリティを考えると大事なものである。あくまでも求められる機能が相対的に少ないということを言いたいのだ。 ↩ HTTPSの暗号化アルゴリズムが複数存在するのは、いずれかが破られても、別のアルゴリズムはすぐには破られないだろうという理由からである。 ↩ 案外考え方としては悪くなかったのではないかと思う。ただ、HTMLのシングルページ志向との相性が絶望的に悪かっただけだ。<head>もファイル分読み込まなくてはいけないしね。 ↩ 例えば、スマフォアプリがPWAで動いているのが、OSごとのアプリに変わるのではないかということだ。そんな世の中になるのはFSFが黙っちゃいないだろうが。 ↩ 非常に問題のある名前である。Javaとはマギー (俳優さんとモデルさんの二人いるからややこしい) とマギー審司くらい違う。 ↩ おそらく標準ECMAScriptという共通言語を各ブラウザの方言に変換するというスタンスをバベルの塔の崩壊に見立てているのだろう。実に洒落の利いた命名である。 ↩ (2022/3/27)Mozillaのかつてのマスコットキャラが恐竜だったり、Chromeの隠し要素に恐竜がジャンプするゲーム chrome://dino/ があったりと、HTMLを恐竜に例えるのは割と古くからあったりする。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSSでリストマーカーを作成する。

CSSでリストマーカーを作成する。 CSSのリストマーカーはdiscなどがあるが、色を変更することや形を変更することができない。 css li { position:relative; padding-left:15px; list-style :none; } li:before { content:""; width:10px; height:10px; background:#ff0000; position:absolute; left:0px; top:5px; } 上の例では赤い四角のリストマーカーが作成できる。 丸いマーカーが欲しい場合は li:beforeの中にborder-radiusを追加する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSSでリストマーカーを作成する

CSSでリストマーカーを作成する CSSのリストマーカーはdiscなどがあるが、色を変更することや形を変更することができない。 css li { position:relative; padding-left:15px; list-style :none; } li:before { content:""; width:10px; height:10px; background:#ff0000; position:absolute; left:0px; top:5px; } 上の例では赤い四角のリストマーカーが作成できる。 丸いマーカーが欲しい場合は li:beforeの中にborder-radiusを追加する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【4日目】メモ帳アプリの作成 [1]

1.本日の課題 今回はメモアプリを作る。最初は単純な仕組みから始めていき、途中からいろいろな要素を足していこうと思います。 まずはテキストボックス内に入力した文字を、ボタンを押したら表示できるようにするところから始めていきます。 <html> <head> <title>メモ</title> </head> <body> <input type="text" id="writeMemo" value="" /> <input type="button" value="save" onclick="saveMemo()" /> <hr> <div> メモ記録領域 </div> <p id="outputMemo"></p> </body> <script> function saveMemo() { let writeMemo = document.getElementById('writeMemo'); let data = writeMemo.value; let outputMemo = document.getElementById('outputMemo'); outputMemo.innerHTML += `<p>${data}</p>`; } </script> </html> このプログラムの流れを説明すると、 テキスト入力枠のidwriteMemoを取ってくる dataにwriteMemoのvalueを取得させる テキスト出力枠のidoutputMemoを取る 出力枠のinnerHTMLにdataを表示する枠を追加させる 今度はlocalStrageを用いて、ページをリロードしてもデータが削除されないようなメモ帳を作ります。まずは1つだけを保存できるようにプログラムを組みました。 <html> <head> <title>メモ</title> </head> <body> <input type="text" id="writeMemo" value="" /> <input type="button" value="save" onclick="saveMemo()" /> <input type="button" value="load" onclick="loadMemo()" /> <hr> <div> メモ記録領域 </div> <p id="outputMemo"></p> </body> <script> function saveMemo() { let writeMemo = document.getElementById('writeMemo'); localStorage.setItem('writeMemo', writeMemo.value); } function loadMemo() { let outputMemo = document.getElementById('outputMemo'); outputMemo.innerHTML += `<p>${localStorage.getItem('writeMemo')}</p>`; } </script> </html> ここではちゃんとlocalStrageにデータが保存されているのかを確認するためにsaveボタンとloadボタン(それぞれ保存と読み込み)を作りました。saveで入力欄に書いてある文字列を保存し、loadでその文字を出力することができます。ただし、saveは新しいものを保存しようとするとデータが上書きされてしまいます。 2.本日学んだこと 本日新たに学んだものはlocalStrage関数です。今回使った関数を簡単に説明します。 localStorage.setItem('キーの名前', 保存するデータ); localStorage.getItem('キーの名前'); 使い方としては、データを保存したいときにはsetItemを使用してキーの名前を設定し保存するデータを入力します。そして取り出すときはgetItemを使用し、取り出したいキーの名前を記入します。これが今回使ったlocalStrageの簡単な動作です。 今回はデータを一つまでしか保存できなかったので、次回は複数個のデータをlocalStrageに格納する方法とプログラムを投稿します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む