20211123のCSSに関する記事は7件です。

【THE THOR】アーカイブ記事をオシャレにする9つのカスタマイズ

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

【C#】WebアプリケーションのレイアウトはCSS Grid Layoutで決まり!

はじめに この記事ではC#+WPF開発者向けにCSS Grid Layoutを紹介します。C#開発者以外のみなさんごめんなさい。 Webアプリケーションのレイアウト、どうするの? 今までデスクトップアプリケーション開発しかしてこなかったC#erのみなさんがある日突然Webアプリケーションを開発することになったときにぶつかる問題、それがレイアウト。 WPFならできるんじゃ~俺にWPFを返せ! と発狂?したくなります(なりました)。そこでおすすめしたいのがCSS Grid Layout。 CSS Grid Layoutとは? おおよそWPFの Grid です。説明終わり。 ちゃんと説明すると、割と新しめのCSSでのレイアウト手法です。比率を含むような様々な範囲で幅・高さを指定して要素を分割できます。WPF(C#のデスクトップアプリケーション用フレームワーク)に近い使用感ということで、従来のWebページというよりはSPAなどのモダンなWebアプリケーションの開発に向いていると思います。 使ってみよう Blazor WebAssemblyでWebアプリケーションを作成中の方へ Blazor WebAssemblyの初期のテンプレートでは自動的にFlexboxというレイアウト手法が適用されており、競合しますのでまずそちらを解除します。 SharedディレクトリのMainLayout.razorを開きます。以下の例は.NET6の場合です。.NETのバージョンにより多少違いがあります。 MainLayout.razor @inherits LayoutComponentBase <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <article class="content px-4"> @Body </article> </main> </div> Article タグのclass属性の値、content px-4 をBootStrapが認識し勝手にFlexboxレイアウトにされるのでclass属性ごと消します。 (ここまでBlazor WebAssemblyの方のみ) まず、ページの最上位に適当な要素( div )を配置し、IDをつけます。 次に、設定したIDに対してCSSを当てて、Grid Layoutを設定します。 index.razor @page "/" <style> #primaryEditorContainer { display: grid; width: 100%; height: 100vh; max-height: 100vh; margin: 0px; padding: 6px 12px; } </style> <div id="primaryEditorContainer"> </div> display:grid でCSS Grid Layoutになります。 一般にはWebページのレイアウトは無限に長くできる「ページ」のようなものがあり、それに向かってレイアウトするイメージです。 しかし、Webアプリケーションではそのような無限に長くなるページではなく、有限の大きさのデバイスのスクリーンに向かってレイアウトしたいでしょう。 width: 100%; height: 100vh; max-height: 100vh; vw vh はデバイスのスクリーンの大きさを基準とした%単位の大きさです。100vhと記述することでスクリーンの大きさと同じ大きさになります。 この例では横方向は(ナビゲーションバーが入るので)厳密にスクリーンとは一致させていません。 ここまでの設定により、最上位として設定した div 要素はちょうど、WPFのテンプレートで最上位にある Grid のように振る舞います。 子要素を割り付ける レイアウトの定義 子要素の大きさの設定方法を説明します。WPFならば MainWindows.xaml <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> </Grid> ですが、CSSでは #primaryEditorContainer { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr; } のように、grid-template-{なんちゃら}を使います。 frは見慣れない単位ですが、比率を表すものです。 WPF CSS 1* 1fr auto auto 150px 150px と、単位系はほぼwpfのGridと互換です。 子要素の配置 子要素側の設定は、WPFの場合 MainWindow.xaml <Grid Grid.Row="0"> ですが、 Index.Razor <div style="grid-row:1"> となります。今回はWPFぽくインラインで設定しましたが、適当なIDを設定して一括で当てても構いません。 インデックスの番号は1始まりです。 あくまでCSSですので、RowとColumnを同時に指定したければ;で区切って同時に詰め込んでOKです。 MainWindow.xaml <Grid Grid.Row="0" Grid.Column="0"> Index.Razor <div style="grid-row:1;grid-column:1;"> 要素のはみ出し さて、Gridで指定した大きさより子要素の実際の大きさのほうが大きかった場合何が起こるでしょうか。 WPFの場合、はみ出した分が単純に描画されません。その代わり、全体のレイアウトは保たれます。 一方、CSS Grid Layoutでは親要素が勝手に大きくなります。すべてのコンテンツが見える代わりに、レイアウトが崩壊します。 height:100vh指定でも平気で画面以上のサイズになります。 はみ出し方を調整するには overflow-{x or y}:{options}を子要素に指定します。例えばoverflow-y:scrollと指定すると縦方向にはみ出しそうになったときにスクロールバーが表示され、はみ出さなくなります。{options}の部分に書けるのは、およそhidden(はみ出した分は描画しない,WPFの挙動に近い) scroll(スクロールバーを出す) visible(はみ出す)の3通りです。完全な説明はドキュメント を参照してください。 上付き・下付き 高さがautoまたは固定長(150px,20vhなど)の要素と高さが比率(1frなど)の要素を混在させると上付き・下付きの要素(上下に固定して表示される要素)が作成できます。 WPFと同じ仕様ですが、実際のWebアプリケーション開発では結構役に立つと思います。 要素を重ねる 同じRowかつColumnの要素を複数用意すると重なります。基本的にWPFと同じです。 子要素にz-indexをcssで指定すると重ねる順番を変えられます。レイアウトの自由度が広がる便利な機能です。 その他 WPFのGridSplitterに相当するものはないようです。 実例 手前味噌ですが、私が開発中のBlazor WebAssemblyを使用したC#開発環境での例をご紹介します。 ロジック部分は省略しますのでお察しください。 現時点での内容と変わらないことは保証できませんがここに実物があります。 CodeEdit.razor @using System; @using System.Collections.Generic; @using System.Linq; @using UiLogics; @using WorkerConnection; @inject HttpClient Http; @inject IJSRuntime JS; @inject CompileQueueService CompileQueue; @page "/CodeEdit" <style> #primaryEditorContainer { display: grid; width: 100%; height: 100vh; max-height: 100vh; grid-template-columns: 1fr; grid-template-rows: 1fr repeat(3,auto) 20vh; margin: 0px; padding: 6px 12px; } .width-matchParent { width: 100% } .tab-active { background-color: white } .header-nonselected { color: GrayText } .tab-content { } .visible { visibility: visible } .hidden { visibility: hidden } </style> <div id="primaryEditorContainer"> <div style="grid-row:1;overflow-y:scroll;"> <WasmCsTest.Components.CodeEditor @bind-UserCode="userCode" @bind-UserCode:event="OnChanged" CodeEditorContext="CodeEditorContext" /> </div> <div style="grid-row:2;"> @if (IsCompiling) { <button class="width-matchParent btn btn-outline-primary">コンパイル取消(未実装)</button> } else if (IsRunning) { <button class="width-matchParent btn btn-outline-primary">プログラム強制終了(未実装)</button> } else { <button class="width-matchParent btn btn-primary" @onclick="OnRunButtonClicked">実行</button> } </div> <div style="grid-row:3;"> <hr /> </div> <div style="grid-row:4;"> <ul class="nav nav-tabs"> <li class="nav-item"> <button class=@tab0.HeaderClassString @onclick="tab0.OnHeaderClick">実行結果</button> </li> <li class="nav-item"> <button class=@tab1.HeaderClassString @onclick="tab1.OnHeaderClick">コンソール</button> </li> </ul> </div> <div class="@tab0.ContentClassString" style="grid-column:1; grid-row:5; padding:6px;"> <WasmCsTest.Components.CompileResult CodeEditorContext="CodeEditorContext" /> </div> <div class="@tab1.ContentClassString" style="grid-column:1; grid-row:5;"> <WasmCsTest.Components.VirtualConsole CodeEditorContext="CodeEditorContext" /> </div> </div> 行 内容 大きさ 1 コードエディタ 1fr(残り全部) 2 実行ボタン auto 3 境界線(hr) auto 4 タブ切り替えボタン auto 5 コンパイラメッセージ 20vh 5 コンソール 20vh と設計されています。5行目のタブ部分は、class属性の内容をC#コードとバインディングして、visibilityを書き換えることで擬似的にタブを実装しています。 同じrow と column を指定して重ねています。重ねる場合は両方明示的に指定しないと重なりません。 1行目が1fr指定なので他の要素は下付きになります。 さいごに WPFのグリッドが直線的なレイアウトならほぼ表現できるくらい強力なように、CSS Grid Layoutも非常に強力です。WPFと割と似ているのもC#開発者的には楽なポイントでしょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web APIを使って、特定の音声に対して返答するWebアプリの作成

背景 ひとり暮らししていると 家に帰って「ただいま」 といっても返答がない  悲しい… そんなことありますよね。 この悲しさを少しでも緩和してくれるアプリを作成しました。 制作物 このCodepenを参考にしました。 こちらのCodePenでは音声の認識と出力が別になっています。 今回は、 Web APIを使用し、特定の入力音声に応じて音声が出力されるように作成しました。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>あいさつ返答</title> </head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script> <body> <h1>あいさつ返答アプリ</h1> <div id="app"> <p> 音声読み込み <button @click="listen">{{ recogButton }}</button> {{ result }} </p> <p> 発話させる(日本語)<br> <input v-model="message" /> <button @click="say">しゃべって!</button> </p> </div> <script> //音声認識 const app = new Vue({ el: '#app', data: { recogButton: 'スタート!', recog: null, result: '', speech: null, message: '', }, mounted() { // 音声認識の準備 const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.msSpeechRecognition || null; this.recog = new SpeechRecognition(); this.recog.lang = 'ja-JP'; this.recog.interimResults = false; this.recog.continuous = false; // 音声認識が開始されたら this.recog.onstart = () => { this.result = ''; this.recogButton = '聴き取り中…'; }; // 音声を認識できたら this.recog.onresult = (event) => { // 認識されしだい、this.resultにその文字をいれる // Vueなので、文字をいれただけで画面表示も更新される this.result = event.results[0][0].transcript; //修正箇所 if (this.result == 'おはよう' || this.result == 'おはようございます') this.speech.text = this.result; else if (this.result == 'いただきます') this.speech.text = '召し上がれ'; else if (this.result == 'ごちそうさま' || this.result == 'ごちそうさまでした') this.speech.text = 'お粗末さまでした'; else if (this.result == 'ただいま') this.speech.text = 'おかえり'; else if (this.result == 'ただいま帰りました') this.speech.text = 'おかえりなさいませ、ご主人様'; else if (this.result == 'ありがとう' || this.result == 'ありがとうございます') this.speech.text = 'どういたしまして'; else if (this.result == 'ごめんなさい' || this.result == 'すいません') this.speech.text = '気にしないでね'; else if (this.result == 'こんにちは') this.speech.text = this.result; else if (this.result == 'はじめまして') this.speech.text = this.result; else if (this.result == 'お疲れ様' || this.result == 'お疲れ様でした' || this.result == 'お疲れ') this.speech.text = this.result; else this.speech.text = "すみません、よくわかりません"; return new Promise((res) => { this.speech.onend = () => res(); speechSynthesis.speak(this.speech); }); }; // 音声認識が終了したら this.recog.onspeechend = () => { this.recog.stop(); this.recogButton = '再開'; }; // 認識できなかったら this.recog.onerror = () => { this.result = '(認識できませんでした)'; this.recog.stop(); this.recogButton = '再開'; }; // 発話の準備 this.speech = new window.SpeechSynthesisUtterance(); this.speech.lang = 'ja-JP'; // または、ブラウザが対応している言語のうちja-JPな最初のボイスを使う window.speechSynthesis.onvoiceschanged = () => { const voices = window.speechSynthesis.getVoices(); this.speech.voice = voices.find(voice => voice.lang == 'ja-JP'); console.log(this.speech.voice); }; }, methods: { // 認識(聞き取り) listen() { this.recog.start(); }, // なんかしゃべる(いちおう非同期対応) async say() { return new Promise((res) => { this.speech.text = this.message; this.speech.onend = () => res(); speechSynthesis.speak(this.speech); }); }, }, }); </script> </body> </html> 完成したコードペン 変更点とコード解説 this.recog.onresultメソッド内のthis.resultに入力された音声が格納されるため そこをif文で条件分岐させました。 返答させたい文章がthis.speech.text変数に格納されています。 もっといろんな音声に対応させたい場合はforkして編集してみてください。 Tips ■CodePenのプラグイン  各言語の右側に歯車マークがあります。  そこでプラグインの設定や確認ができます。  CodePen外で使用する際は、適宜挿入が必要でした。 ■Web API ・これいれるだけでバイブレーションが使えます。  何かに使用できそうです... window.navigator.vibrate(2000); ・公式ドキュメント > インターフェース  大量にありますが、いずれ全てに目を通したいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

hoverで変化するsns共有ボタン

Fontawesomeを使ったiconは便利ですよね、ただシンプルなので味気ない気もします。 今回はちょっとアレンジしたいと思います! 前提 HTML CSS Fontawesome(CDN) Bootstrap (CDN) だけで実装可能です! 動作はこちらで確認してください  実装 まずはHTMLファイルのheadに以下のコードを追加してください index.css <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <link rel ="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.css"> これでFontawesomeとBootstrapが使えます。 使用アイコン 以下のように描くことでTwitterとInstagramのアイコンが使えます index.css <i class="fab fa-twitter fa-3x"></i> <i class="fab fa-instagram fa-3x"></i> /*-「fa-3x」と書いているのはサイズを大きくしているからです。消してもらっても構いません-*/ これでアイコンの実装が完了しました。 少しアレンジしていきたいと思います。 index.html <div class="row text-center mt-5 pt-5"> <div class="col-6 mb-3"><a href="#" class="tweet"><i class="fab fa-twitter fa-3x"></i></a></div> <div class="col-6 mb-3"><a href="#" class="insta"><i class="fab fa-instagram fa-3x"></i></a></div> </div> *ここで使っているbootstrapのクラスについて説明します row: 画面を12分割する mt, pt: margin-top, padding-topのことです。 1 ~ 5まで指定できます。 text-center: text-align: center;と同じ col-6: rowと合わせて使うことで12分割したうちの6カラム使用するとなります。 mb-3: margin-bottomのことです。1 ~ 5まで指定できます。 アイコンだけだと味気ないので、枠に入れたいと思います。 index.css .tweet{ text-decoration: none; /*--aで括っているのでリンクの下線などを消すために設定しています--*/ color: black; } .tweet i{ border: 2px solid black; border-radius: 50%; /*--ここで丸くしています-*/ padding: 10px; ちょっとだけ見やすくなりましたね! 色も変えちゃいましょう index.css .tweet{ text-decoration: none; color: white; } .tweet i{ border: 2px solid white; border-radius: 50%; padding: 10px; background-color: skyblue; } twitterっぽくなりました! 最後に一工夫です。 このアイコンにカーソルが乗った場合に変化させましょう! index.css .tweet{ text-decoration: none; color: white; transition: all 0.3s ease; } .tweet:hover{ color: blue; } .tweet i{ border: 2px solid white; border-radius: 50%; padding: 10px; background-color: skyblue; transition: all 0.5s ease; } .tweet i:hover{ border-radius: 0; transform: rotate(360deg); background-color: white; border: 2px solid skyblue; } /*----- インスタグラム ------*/ .insta i{ border: 2px solid red; border-radius: 50%; padding: 10px; cursor: pointer; transition: all 0.5s ease; background-color: white; } .insta i:hover{ border-radius: 0; transform: rotate(360deg); background-color: red; border: 2px solid red; } .insta{ text-decoration: none; color: red; transition: all 0.3s ease; } .insta:hover{ color: white; } transitionをhoverさせたい要素に加えることでhoverした時のcssが適用されるまでの時間や動きかたを変更できます。 tweetの例で見ると、0.3秒かけてゆっくり変化させています。 transition: all 0.3s ease; all => どのプロパティに適用するか 0.3s => 「s」か「ms」として指定できます ease => 動きかたの指定 以上で実装をおわります! 注意点としては、transformの指定は"a"タグや"span"タグに対しては指定できないみたいなので注意してください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

疑似セレクタ・疑似要素の活用

擬似クラスを利用すると、マウスホバー状態時など、HTMLのみでは表現できない状態のスタイルを設定できます。 擬似要素はHTML上に直接指定できない要素にスタイルをあてたり、存在しない追加のコンテンツを挿入したりできます。 サンプルのNEWSは、マウスオーバーやドラッグで選択した時のスタイル設定、 2つめ以降の要素にのみマージンを設定したり、CSSだけでNEWの表記を追加しています。 See the Pen Untitled by Ryuta Satonaka (@satonaka) on CodePen.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CSS】メディアクエリ(Media Queries)基礎

メディアクエリを利用したRWD(レスポンシブ・ウェブ・デザイン)の実装 モバイルファースト 小さなビューポートサイズをベースとして、大きなビューポート用のスタイルを上書きしていくスタイル。 上書きするスタイルが少なくなる傾向にある。 flexboxやgridなど、包括する要素が必要になるDOM(HTMLタグ)などを予め想定する必要がある。 /* ベーススタイル */ div { width: 100%; } /* 横幅が321px以上のときのスタイル */ @media (min-width: 321px) { div { width: 100%; } } /* 横幅が769px以上のときのスタイル */ @media (min-width: 769px) { div { width: 640px; } } /* 横幅が769px以上かつ、992px以下のときのスタイル */ @media (min-width: 769px) and (max-width: 992px) { div { width: 800px; } } /* 横幅が993px以上のときのスタイル */ @media (min-width: 993px) { div { width: 1200px; } } PCファースト 大きなビューポートサイズをベースに、小さなビューポート用のスタイルを上書きしていくスタイル。 上書きする項目が多くなる傾向にある。 複雑なPCレイアウトからシンプルなSPへシフトするため、レスポンス想定が比較的容易。 /* ベーススタイル */ div { width: 1000px; } /* 横幅が992px以下のときのスタイル */ @media (max-width: 992px) { div { width: 800px; } } /* 横幅が768px以下かつ、640px以上のときのスタイル */ @media (max-width: 768px) and (min-width: 640px) { div { width: 700px; } } /* 横幅が320px以下のときのスタイル */ @media (max-width: 320px) { div { width: 100%; } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML、CSS、JavaScriptのファイルをリンクさせる方法

はじめに Webサイトの開発をやっているとHTML、CSS、JavaScriptのファイルを主に扱うのですが、その3つのファイルをリンクさせて、HTMLに適用する方法を紹介したいと思います。 環境 Mac OS Monterey MacBook Pro M1 VS Code 本編 主にHTMLのファイルにCSS、JavaScriptを適用させる感じです。 HTMLとCSS head上にこのように記載します。 <link rel="stylesheet" href="ファイル名.css"> HTMLとJavaScript bodyタグの一番最後にこのように付け足します。 <script type="text/javascript" src="ファイル名.js"></script> これで完了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む