20210413のCSSに関する記事は10件です。

Sassについて

デイトラWeb制作コース中級編DAY7の学び 【この記事に書いてあること】 プログラミング学習31日目⏩Web制作コース中級編DAY7?学習時間:3時間34分⏳学習内容:Sassの学習✏学び?1 入れ子形式で書けた2 変数が使えた3 "&"記号で擬似要素が書けた4 「@mixin」でコードの繰り返し記述を防げた#デイトラ#プログラミング初心者#プログラミング学習 pic.twitter.com/Fb9So79iYn— ふりっく?トリプルゼロのWeb制作者 (@FuRiC_twi) April 13, 2021  【学び】 1 【Saasとは】 CSSの拡張言語のこと <Sassのメリット> ① 入れ子(ネスト)形式で書ける ② 変数が使える ③ ”&”記号で擬似要素が書ける ④ @mixinでコードの繰り返し記述を防げる 2 【入れ子】 Sassは、親クラスのカッコの中に、続けて子要素のCSSを書くことができる <入れ子の書き方> <入れ子で孫要素まで書ける> HTMLの改装に合わせて、入れ子を深くすることができる 3 【疑似要素とクラス】 <&で繋げる疑似要素・クラスの書き方> &をつけることで、前の要素をすべて継承できる 左:Sass                         右CSS 4 【変数】 <変数をCSSに組み込む> 「$」マーク+名前をつけて、変数を定義する 画像の例だと、 28 $link-color-active: #da1e32;と定義し、値を変数名にする 左:Sass                         右CSS <変数定義のメリット> 制作途中での仕様変更が一括でできるようになる 定義した、変数の値を変えるだけなので、保守性の高いコードになる <四則演算もできる> ①$link-font-size: 16px;で16pxの値に変数名を定義 ② 値に$link-font-sizeを記入し、四則演算する 画像の例だと、16px+10pxで.active が26pxになっている 5 【定義したスタイル使う】 <@extend> すでに設定してあるスタイルを、別のクラスに引き継ぐこと 共通で使いたいスタイルを予め設定し、それを@extendすることで、何回も同じコードを書かなくて済む <@mixin> 一部だけ仕様を変更したいが、ほとんど同じ型のときは、@mixinを使う @mixinを反映させたいときは、@includeを使う 6 【mixinを使ったメディアクエリの設定方法】 予め定義したメディアクエリを@mixinで呼び出す <従来のメディアクエリの書き方> よくないポイント ・コード量が長い ・クラス名ごとに書かないといけない ・ディアクエリ用にもう一度コードを書き直さないと行けない style.css @media screen and (max-width: 767px) { .header { height: 60px; } } <@mixinを使ったメディアクエリの書き方> いいポイント ・コード量が減る ・どこのクラスに対するメディアクエリかを視覚的に判断できる ・対象のクラスにそのままメディアクエリを書くことができる style.css .header { height: 100px; /*PC用の表示*/ @include mq() { /*メディアクエリ用*/ hight: 60px;         } } <メディアクエリ用のmixinの作り方> ① マップ型変数 breakpointsを定義 style.css $breakpoints: ( /*キー(変数名) : 値*/ 'sp': 'screen and (max-width: 767px)', /*767px以下(スマホ)用の表示*/ 'pc': 'screen and (min-width: 768px)' /*768px以上(タブレット・PC)用の表示*/ ) !default; ② ディアクエリ用のmixinを定義 style.css @mixin mq($breakpoint: sp) { /*1 mixinを「mq」を名付ける 2 ここの「sp」の部分は、breakpointsで定義した、変数名を入れる*/ /*map-get(マップ型変数, キー)で値を取得*/ @media #{map-get($breakpoints, $breakpoint)} { /*2で入力された変数名を元に値が呼び出される*/ /*この中をカスタムできる*/ @content; } } ③ メディアクエリ用のmixinを呼び出す style.css .header { height: 100px; /*PC用の表示*/ @include mq ("sp") { /*メディアクエリ用*/ height: 60px; } } 7 【functionについて】 Sassは関数も使える style.css @function activeFontSize ($base-size) { /*activeFontSize ()というfunctionを定義して、引数に$base-sizeを定義*/ @return $base-size + 2px; /*$base-sizeに2pxを足した値を返り値にする*/ } $link-font-size: 16px; /*$link-font-sizeという変数に、16pxと定義*/ .active { font-size: activeFontSize ($link-font-size); } /* クラス名「.activer」のフォントサイズの値が18pxになる*/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

静的に入力されたtableの値と、Chart.jsを連携してみた

ある案件で、tableに入力された値と、Chart.jsを連携する実装がありました。 今回は円グラフを使用しましたが、他のグラフでも応用可能だと思います。 参考になれば、幸いです。 はじめに table構造はとてもシンプルです。 (実際の運用では、それぞれの数値に関してhtmlは触らずに、WordPressのカスタムフィールドでの運用を想定しています。) See the Pen table - basic by dan (@___dan) on CodePen. このtableを元に、以下の2つのパターンを実装しました。 カテゴリ毎の合計値 (tableでは年度別の合計値が出力されているが、Chart.js上ではカテゴリ毎の合計値を出力する。) 対合計比 (総計を基準にし、各カテゴリの合計値が何%なのかを出力する。) 実装編 カテゴリ毎の合計値 See the Pen table(total) - chart.js by dan (@___dan) on CodePen. 記述したjsは以下の通りです。 (trをscope範囲とし、それぞれの数値が記入されているtdをtargetとする。) //空の配列を用意 let total = []; $('.scope').each(function () { let target = $(this).find('.target'); let sum = 0; for (let i = 0; i < target.length; i++) { //取得したtextが文字列のため、parseIntで数値型に変換 //sum = $(target[i]).text() * 1 + sum;のように、1を掛けて数値型に変更するのもアリかと思います。 sum = parseInt($(target[i]).text()) + sum; } //push()メソッドを使用して、sumの値を配列でtotalへ返却 total.push(sum); }); console.log(total); //実行結果[60, 30, 6, 96] - カテゴリ毎の合計値が配列に格納 Chart.js内のdataに、作成したtotal変数をセットしてあげて完成です。 data: total なお、optionsの値がブラウザで確認したところ正常に動いていたのですが、 codepenで確認すると丸々抜けているようです、、、。 (本来であれば、円グラフの上に「進学先 人数」というタイトルと、ホバーしたときのラベルが〇〇人と表示されます。) options: { title: { display: true, text: '進学先 人数' }, tooltips: { callbacks: { label: function (tooltipItem, data) { var label = data.labels[tooltipItem.index]; if (label) { label += ': '; } label += data.datasets[0].data[tooltipItem.index] + '人'; return label; } } } } 対合計比 See the Pen table(ratio) - chart.js by dan (@___dan) on CodePen. ※こちらもoptionsの値が動いておりません、、、。 (本来であれば、円グラフの上に「進学先 割合」というタイトルと、ホバーしたときのラベルが〇〇%と表示されます。) 追加記述したjsは以下の通りです。 //空の配列を用意 let ratio = []; //先ほど取得したtotalの値が[60, 30, 6, 96]だが、合計値である96は不必要なのでlengthから-1する for (let i = 0; i < total.length - 1; i++) { //total[i] - totalのi番目、つまり0番目の場合は60を取得 //[total.length - 1] - 配列の最後の値である96を取得(全体の合計値) let calc = (total[i] / total[total.length - 1]) * 100; ratio.push(calc); } console.log(ratio); //実行結果[62.5, 31.25, 6.25] - 合計値に対する、各カテゴリの割合が格納 Chart.js内のdataに、作成したratio変数をセットしてあげて完成です。 data: ratio おわりに 公式サイトでは、設定するdataの値が静的に配列で記述されていますが、 そのdataに、自分で作成した変数をセットすれば様々な要件に対応できるかと思います。 ※Chart.jsの基本的な使い方については、下記のサイトを参考に致しました。 Chart.jsでグラフを描画してみた 参考サイト Chart.js公式サイト Tooltipsの設定値一覧 Chart.jsでグラフを描画してみた pushで配列に要素を追加する方法
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sass(SCSS)を使って絵を書いてみた

Sassの学習がてら絵を書いてみたので記事にしてみました。この記事を通してSassやCSSで絵を書く楽しさ(ついでにSassの使い方)を伝える事ができれば幸いです。 作品 CodePenなるものを発見したのでQiitaの記事を書くためだけに導入しました。 See the Pen rNjpGBa by すぐひと (@suguhito65) on CodePen. Sass 今回使用したSassの機能を簡単にではありますが解説してみたいと思います。 変数 scss $body: #ffd700; .head { background-color: $body; } キャラクターの体の色を変数$bodyに入れ、使う時はbackground-color等の値のところに代入します。 色を変更したくなった時に変数の値だけ変更すれば、変数が使われている所の全ての色が変更できるので便利です。 @mixinと@include CSSで絵を書く際よく使うプロパティを@mixinでまとめといて、必要になったら@includeで取り出すイメージですかね。 scss @mixin ptlm($margin) { position: absolute; top: 50%; left: 50%; margin: $margin; } .head { @include ptlm(-7em 0 0 -4em); } .left-eye { @include ptlm(-2.3em 0 0 0em); } position〜leftは固定の部分ですがmarginはそれぞれのクラスによって値が違うため、ptlm(任意の名前)の引数に$marginを入れます。そして、いざクラスでptlmを使いたい時は@includeを使用し、()内にmarginの値を入れて使用します。 ちなみに私がCSSで絵を書く際、topやleft(もしくはrightやbottom)でだいたいのあたりをとってからmarginでポジションの微調整をするのが常でしたが、今回はmarginにポジション取りの全権を与えました。その方がmarginひとつを引数にすればいいので、コードがスマートになりました。 ネスト(入れ子)と& scss .tail { @include ptlm(3.2em 0 0 3.6em); @include hw(1.5em, 1.8em); @include border(0.3em); background: #8b4513; transform: skewX(-10deg) rotate(-20deg); &::before { @include ptlm(-3.1em 0 0 -0.4em); @include hw(2em, 2.5em); @include border(0.3em); content: ''; background: $body-s; } &::after { @include ptlm(-6.5em 0 0 0.8em); @include hw(4em, 5em); @include border(0.3em); content: ''; background: $body-s; } .tail-arrange { @include ptlm(-2.85em 0 0 0.7em); @include hw(1.1em, 1.8em); background: $body-s; z-index: 1; &::before { @include ptlm(1.55em 0 0 -1.75em); @include hw(0.5em, 0.83em); content: ''; background: #8b4513; } } } ネストを使う事でtailとtail-arrangeの親子関係がわかりやすいですね。&を使う事でbefore・after等の擬似要素やhover・active等の擬似クラスもネストできます。 ちなみに絵を書く時にbeforeとafterをよく使います。これらを使うと1つのdivタグで3つの図形を作れるので便利ですね。contentがないと反映されないので忘れずに(値は空にします)。 CSSで絵を書くために CSSで絵を書くために一番重要なのは図形の成形でしょうか。思い描く形を作り出す事が難しくもあり、楽しい部分でもあります。 三角形 scss .nose { @include hw(0, 0); /* heightとwidthが0 */ border-left: 0.27em solid transparent; border-right: 0.27em solid transparent; border-bottom: 0.3em solid #000; } 鼻の部分(三角形)の作り方は、heightとwidthを0にしてborderのleftとrightをtransparent(透明)にする事でできます。border-bottomの色がそのまま三角形の色になります。 See the Pen eYgywor by すぐひと (@suguhito65) on CodePen. ↑の図形の方が理解しやすいでしょうか?border-topを記述しない状態が三角形です。 台形 See the Pen dyNJBpg by すぐひと (@suguhito65) on CodePen. 例えば↑のようにtransformを使う事で台形ができます。height・width・background-colorで作った四角形をtransformを使って変形させる事で、いろんな形が作れるので純粋に楽しいです。 transformは他にもいろんな使い方があるようなので、興味のある方はぜひ調べてみて下さい。 丸みのある図形 See the Pen ZELvgPN by すぐひと (@suguhito65) on CodePen. border-radiusを4つに分けて記述した方がわかりやすいと思ったので分けています。 値は、(top-leftの場合)横50px・縦20pxの順番で記述し、その範囲を丸くしてくれます。%を使う事もでき、4つ全てを50%にすると円になります。 transformと組み合わせれば、できる図形の幅が広がります。 アニメーション Sassと同時に今回初めて取り入れてみたので、さほど詳しくありませんが使用した機能だけでも解説してみます。 See the Pen wvgyYyQ by すぐひと (@suguhito65) on CodePen. アニメーションと言えばtransitionとanimationがありますが、今回はanimationを使用しました。animationと@keyframesを使う事でアニメーションを繰り返したり、繰り返す時間の間隔を指定できたりします。 scss .ear2 { animation: ear2-move(アニメーション名) 1s(時間) infinite alternate ease-in-out; } infiniteは無限にアニメーションを再生する設定で、alternateが行ったり来たりの設定です(normalは行くだけ)。ease-in-outはアニメーションのタイミング・進行割合を指定する値の一つです(他にlinear、ease-in、ease-out等)。 scss @keyframes ear2-move { 0% { transform-origin: bottom right; transform: rotate(0deg); } 10% { transform-origin: bottom right; transform: rotate(30deg); } 20% { transform-origin: bottom right; transform: rotate(0deg); } 100% { transform-origin: bottom right; transform: rotate(30deg); } } @keyframesでアニメーションの動作を指定します。今回はtransformのrotateで30度回転させるアニメーションです。transform-originは回転の中心を設定するプロパティで、↑は回転の中心を右下に指定しています(他にcenter等)。0%〜100%は1s(1秒間)の中での動き方を指定するものです。 終わりに HTML&CSSやSassの学習をする際、できる事なら楽しんで学習したいものです。私の場合は、CSSで絵を書く事で楽しく学習できています。興味のある方はぜひ試してみて下さい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flex.boxの基礎を理解すると。

初心者が独学1年では理解できなかったFlexboxを プログラミング学校に通ったことによってめちゃくちゃ理解できたのでご報告いたします。 Flex.boxを理解するためには『HTML,CSS』を理解している必要があるなと実感 『HTML』を装飾するためのツールの一つとしてFlexboxが存在する 『Flexbox』を理解するために用意するモノ ・CSS Flexbox チートシート (ダウンロード) 以上。 文章で表現は難易度高いので、Flexboxを使って次回から『国旗』を作ります 今回は以上です! ありがとうございます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

よく使うflexの横並びスクロール

よく使うflexの横並びスクロール 末尾に余白用の擬似要素を追加するのがポイント ul { display: flex; flex: 1; overflow-x: scroll; white-space: nowrap; li { margin-left: 8px; display: inline-block; &:first-of-type { margin-left: 16px; } &:last-of-type { position: relative; &::after { position: absolute; top: 0; left: 100%; width: 16px; height: 1px; content: ''; } } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

よく使うcss

要素にそれっぽい影をつける XDのデフォルトの値でデザイナーがこのままの値を使う box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16); flexの横並びスクロール スクロールバー非表示と、末尾に余白用の擬似要素を追加するのがポイント ul { display: flex; flex: 1; overflow-x: scroll; white-space: nowrap; &::-webkit-scrollbar { display: none; } li { margin-left: 8px; display: inline-block; &:first-of-type { margin-left: 16px; } &:last-of-type { position: relative; &::after { position: absolute; top: 0; left: 100%; width: 16px; height: 1px; content: ''; } } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSSやjQueryでできるアニメーション!

CSSやjQueryでwebページにつけるアニメーションを自分のメモとしてまとめました。 *いろいろなサイトを参考にさせていただきました。 ページをスクロールするとクラスが追加される。 ページをスクロールしていくとclassNameに”some class!”部分のクラスが追加される。 jQuery $(function() { $(window).scroll(function() { $(".className").each(function() { var scroll = $(window).scrollTop(); var blockPosition = $(this).offset().top; var windowHeihgt = $(window).height(); if (scroll > blockPosition - windowHeihgt) { $(this).addClass("some class!"); } }); }); }); 画面ロード中にアニメーションを表示 画面ロード中に黄色い円が出ます。htmlに.loaderを持つクラスが必要。 cssを変えることでいろいろ表示できる。 最後に紹介しているEpic spinnerのサイトなどでローディングアイコンをコピーしてCSSとHTMLに張り付ければかっこいいのを作れる。 css .loader { align-items: center; background: #fff; bottom: 0; display: flex; justify-content: center; left: 0; position: fixed; right: 0; top: 0; z-index: 999; } .loader::after { animation: loader 0.5s linear infinite; border: 1px solid orange; border-radius: 50%; border-right: 5px solid rgba(orange, 0.2); border-top: 5px solid rgba(orange, 0.2); content: ""; height: 70px; width: 70px; } @keyframes loader { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } } jQuery $(window).on('load',function(){ $(".loader").fadeOut(); // これだけで }); ふわふわと揺れる htmlにfuwafuwaクラスをつけると適用される。backgroundのurlはお好みで css //CSS .fuwafuwa { animation: fuwa 4s infinite ease-in-out .9s alternate; background: url(image) no-repeat center center / 60px auto; display: inline-block; transition: 1.5s ease-in-out; } @keyframes fuwa { 0% { transform:translate(0, 0) rotate(-7deg); } 50% { transform:translate(0, -7px) rotate(0deg); } 100% { transform:translate(0, 0) rotate(7deg); } } くるくる回って出現 htmlにkurukuruクラスをつけると適用される。 css .kurukuru { background: linear-gradient(to right, #362ae0 0%,#3b79cc 50%,#42d3ed 100%); width: 50px; height: 50px; opacity: 0; padding-bottom: 40px; } .kurukuru.is-animated { animation: kurukuru 1.4s ease-out; opacity: 1; } @keyframes kurukuru { 0%{ transform: rotateY(0) translateY(40px); opacity: 0; } 100%{ transform: rotateY(360deg) translateY(0); opacity: 1; } } 最後に いろいろ追加していきたいと思います。 便利なサイト Epic spinner https://epic-spinners.epicmax.co/#/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フロントで利用する単位について

職場で、単位についての研修があったので、それのまとめです。 タグの大きさ指定 px 1dot(ドット)=1px(ピクセル) パソコンの画面の表示は小さな点の集合体で構成されていて、その最小単位が1dot % 親に対して何%の表示をするか vw(viewportwidth) 画面幅に対して何%の表示をするか 文字の大きさ指定 % 親に対して何%の表示をするか 何もしていなければHTMLの初期値からの倍率 HTMLの初期値=16px em 1em=1文字 ※現在はスマホやPCの表示に柔軟に対応できないため、利用されるケースは少ない rem emの上位互換 htmlタグを親として倍率調整する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CSS】俺のFLOCSSディレクトリとファイル構成のベース(個人用)

個人用のメモ。プロジェクトで共通化できる、FLOCSSのディレクトリやファイル設計について。 (参考)FLOCSSの詳細や強度・考え方 速度改善を目指したFLOCSS構造 FLOCSSの構造は基本に沿うが、ブラウザの読み込み速度改善のため、コンパイルするファイルは全体共通部分とページ毎に必要な部分で分ける。 (通常は、app.scssでまとめて@importして、コンパイルしたapp.cssを読み込む) foundation サイト全体で共通のデフォルト設定。 ├ _normalize.scss 不要なデフォルトスタイルをリセット(reset.cssよりも軽量) ├ _base.scss 全体で共通のリセットスタイル ├ _variable.scss 変数をまとめるファイル ├ _mixin.scss mixinをまとめるファイル layout 全体で共通のページのレイアウト ├ grid グリッド関連のCSSを保存(googleのマテリアルデザインを使用)  ├ _grid.scss  ├ _mixin.scss  ├ _variable.scss ├ _container.scss ├ _header.scss ├ _footer.scss object プロジェクト毎や再利用可能など細かいスタイルを保存するディレクトリ ├ component いくつかのページで共通するモジュール  ├ _button.scss  ├ _link.scss  ├ … ├ project ページ毎に固有のモジュール(他のページで使わない)  ├ top   ├ _card.scss   ├ _profile.scss  ├ ページ名... ├ utility 強制的に適用するスタイル(!importantがつくもの)  ├ _display.scss  ├ _margin.scss  ├ _padding.scss  ├ _typography.scss ├ common_inview.scss 全体で共通のファーストビュー用のスタイル。 ├ common_overview.scss 全体で共通のファーストビュー以外のスタイル。 ├ top_inview.scss トップページ固有のファーストビュー用のスタイル。 ├ top_overview.scss トップページ固有のファーストビュー以外のスタイル。 ├ (ページ名)_inview.scss ├ (ページ名)_overview.scss コンパイル対でないファイルの先頭には_をつけることで、間違ってコンパイルされることを防ぐ。 ポイントはinviewとoverviewを分けることでファストビューで使うスタイルのみ先に読み込み描画速度を上げていること。 詳しくはクリティカルCSSとは?使い方を参照。 また、スタイルの読み込みをページ毎に共通のスタイル(common_inveiwとcommon_overview)とページ毎に使うスタイルだけにし、不要な記述を読み込まないようにする。 これをすることで、レンダリングブロックを回避し、各ページに対して必要なスタイルのみが提供されるので、ページの高速化につなげることができる。 1. foundation :サイト全体で共通のデフォルト設定 1-1. _normalize.scss hタグなどスタイルを初期化する。MIT Licenseのコードを使用。公式ページからダウンロードできる。 ▽normalize.cssとreset.cssの違い normalize.cssはresetと異なり有効なスタイルを残している。 1-2. _base.scss 全体で共通となるスタイルを指定。 _base.scss html { height: 100%; font-size: 62.5%; } body { font-family: 'YuGothic', 'Noto Sans JP', 'Hiragino Kaku Gothic Pro', 'メイリオ', Meiryo, 'Roboto', Roboto, Osaka, sans-serif; display: flex; flex-flow: column; min-height: 100vh; color: text-color(base); } main { flex: 1; } a { color: text-color(link01); text-decoration: none; cursor: pointer; } button { appearance: none; padding: 0; background-color: transparent; border: none; outline: none; cursor: pointer; } html, body, p, ol, ul, li, dl, dt, dd, blockquote, figure, fieldset, legend, textarea, pre, iframe, h1, h2, h3, h4, h5, h6, hr { margin: 0; padding: 0; } ul, ol, li { list-style: none; } ・text-color(変数名) 変数名で指定。別ファイルのvariable.scssに記述してある。 1-3. _variable.scss 変数を記述するファイル。 _base.scss // size $sizes: tb, sp; // font size $fontSizes: 10, 12, 14, 16, 18, 20, 22, 24, 26, 28; // text line $lines: 2, 3, 4; // space $spaces: 0, 8, 16, 24, 32, 40; // breakpoint $breakpoints: ( pc: 1280px tb: 960px, sp: 560px, min: 360px, ) !default; // key color $key-colors: ( pink01: #f47aa9, pink02: #cb678d, black: #333, white: #fff, ); @function key-color($key) { @return map-get($key-colors, $key); } // text color $text-colors: ( base: #333, white: #fff, gray: #999, link01: #0074ad, link02: #666, link02-hover: #333, ); @function text-color($key) { @return map-get($text-colors, $key); } // btn color $btn-colors: ( normal: #fff, normal-hover: #333, cv: #f47aa9, cv-hover: rgba(244,122,169,.8), ); @function btn-color($key) { @return map-get($btn-colors, $key); } text-colorやkey-colorは関数を定義し名前で色を呼び出せるようにする。 ・関数の使い方 map-getメソッドを使うと複数のKey-Valueから指定したキー名をと一致する値を抜き出すことができる。 関数を用意して名前を付け、キー名を引数で渡す。 @function 関数名(引数) { @return map-get(検索元の変数名, 引数で渡した変数名) } 1-4. _mixin.scss mixin(どこでも呼び出せるコンポーネント)を定義するファイル。メディアクエリを定義するために使用。 _base.scss $breakpoint-down: ( 'pc': 'screen and (max-width: #{map-get($breakpoints, 'pc')})', 'tb': 'screen and (max-width: #{map-get($breakpoints, 'tb')})', 'sp': 'screen and (max-width: #{map-get($breakpoints, 'sp')})', 'min': 'screen and (max-width: #{map-get($breakpoints, 'min')})', ) !default; @mixin mq($breakpoint: tb) { @media #{map-get($breakpoint-down, $breakpoint)} { @content; } } $breakpoint-downという変数の中でメディアクエリのパターンを作成する。 画面幅はvariable.scssに記述するためこのファイルは変更しない。 variable.scss // breakpoint $breakpoints: ( pc: 1280px tb: 960px, sp: 560px, min: 360px, ) !default; mqという名前のmixinを作成し、pc, tb, sp, minを指定すれば対応するメディアクエリを表示できるようにする。 なお、scssでの呼び出しは@include mixin名(引数)とする。 ・#{ } 変数をそのまま表示する。 ・@content mixinを呼び出した時に{ }の中に記述した内容を@contentの部分に表示する。 2. layout :全体で共通のページのレイアウト グリッドシステムに関するファイルを保存する。グリッドシステムはgoogleのマテリアルデザインをカスタムしたものを使用。 グリッドシステムに関するmixinとvariableもこのフォルダの中にファイルを作成する。 (参考)Googleのマテリアルデザインのグリッドシステムを使う手順 2-1. gridディレクトリ _grid.scss /* * layout/grid/grid.scss */ @import './variables'; @import './mixins'; :root { @each $size in map-keys($grid-columns) { --grid-margin-#{$size}: #{map-get($grid-default-margin, $size)}; --grid-gutter-#{$size}: #{map-get($grid-default-gutter, $size)}; --grid-column-width-#{$size}: #{map-get($grid-column-width, $size)}; } } // grid .l-grid { max-width: 1024px; transition: all 0.25s; @each $size in map-keys($grid-columns) { @include grid-media-query_($size) { $margin: map-get($grid-default-margin, $size); $gutter: map-get($grid-default-gutter, $size); @include grid($size, $margin, $gutter); } } } .l-grid-cell { // default style min-height: 25px; // select the upper breakpoint $upper-breakpoint: nth(map-keys($grid-columns), 1); @each $size in map-keys($grid-columns) { @include grid-media-query_($size) { $gutter: map-get($grid-default-gutter, $size); @include grid-cell($size, $grid-default-column-span, $gutter); @for $span from 1 through map-get($grid-columns, $upper-breakpoint) { // Span classes. // stylelint-disable max-nesting-depth @at-root .l-grid-cell--span#{$span}, .l-grid-cell--span#{$span}-#{$size} { @include grid-cell-span_($size, $span, $gutter); } } } } } 2-1-2. _variables.scss girdシステム用の変数をまとめたファイル。ブレイクポイントやカラム数などはプロジェクトに合わせ変更。 _variables.scss $grid-breakpoints: ( desktop: 1140px, tablet: 641px, phone: 0, ) !default; $grid-columns: ( desktop: 12, tablet: 6, phone: 4, ) !default; $grid-default-margin: ( desktop: 24px, tablet: 24px, phone: 16px, ) !default; $grid-default-gutter: ( desktop: 24px, tablet: 24px, phone: 16px, ) !default; $grid-column-width: ( desktop: 72px, tablet: 72px, phone: 72px, ) !default; $grid-default-column-span: 4 !default; $grid-max-width: null !default; 2-1-3. _mixins.scss girdシステム用のmixinをまとめたファイル。gridシステムで使うmixinをまとめている。 _mixins.scss @import './variables'; // returns the lower grid boundary or null if the smallest grid is selected @function grid-breakpoint-min($size) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } $min: map-get($grid-breakpoints, $size); @return if($min > 0, $min, null); } // returns the upper grid boundary or null if the largest grid is selected @function grid-breakpoint-max($size) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } $names: map-keys($grid-columns); $n: index($names, $size); $prev: if($n > 1, nth($names, $n - 1), null); @return if($prev, (grid-breakpoint-min($prev) - 1px), null); } // Private mixins, meant for internal use. @mixin grid-media-query_($size) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } $min: grid-breakpoint-min($size); $max: grid-breakpoint-max($size); @if $min == null and $max != null { // Phone @media (max-width: $max) { @content; } } @else if $min != null and $max != null { // Tablet @media (min-width: $min) and (max-width: $max) { @content; } } @else if $min != null and $max == null { // Desktop @media (min-width: $min) { @content; } } @else { // Fallback - no breakpoints defined @content; } } @mixin grid-cell-span_($size, $span, $gutter) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } $percent: percentage($span / map-get($grid-columns, $size)); @if $percent > 100% { $percent: 100%; } width: calc(#{$percent} - #{$gutter}); width: calc(#{$percent} - var(--grid-gutter-#{$size}, #{$gutter})); @supports (display: grid) { width: auto; grid-column-end: span min($span, map-get($grid-columns, $size)); } } // Public mixins, meant for developer usage. @mixin grid($size, $margin, $gutter) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } display: flex; flex-flow: row wrap; align-items: stretch; margin: -$gutter / 2; margin: calc(var(--grid-gutter-#{$size}, #{$gutter}) / 2 * -1); @supports (display: grid) { display: grid; margin: 0; grid-gap: $gutter; grid-gap: var(--grid-gutter-#{$size}, $gutter); grid-template-columns: repeat(map-get($grid-columns, $size), minmax(0, 1fr)); } } @mixin grid-cell($size, $default-span, $gutter) { @if not map-has-key($grid-columns, $size) { @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}"; } @include grid-cell-span_($size, $default-span, $gutter); box-sizing: border-box; margin: $gutter / 2; margin: calc(var(--grid-gutter-#{$size}, #{$gutter}) / 2); @supports (display: grid) { margin: 0; } } 2-2. _container.scss 共通のレイアウトとなるスタイルをまとめるファイル。プロジェクト毎に必要に応じて編集。 _container.scss .l-container { max-width: 960px; margin: 0 auto; padding: 0 24px; @include mq(tb) { width: 100%; } } .l-list { max-width: 640px; margin: 0 auto; padding: 0 0 24px; @include mq(sp) { padding: 0 16px 16px; } } .l-error { max-width: 640px; margin: 0 auto; padding: 0 0 24px; @include mq(tb) { padding: 0 0 16px; } @include mq(sp) { padding: 0 16px 16px; } } .l-btn-container, .l-top-btn-container { padding: 48px 0; } .l-btn-container { @include mq(sp) { padding: 24px 0; } } .l-top-btn-container { background-color: #f5f5f5; @include mq(tb) { padding: 24px 0; } } 2-3. _header.scss 共通のヘッダーのスタイルをまとめたファイル。プロジェクト毎に必要に応じて編集。 _header.scss #l-header { width: 100%; height: 130px; background-color: #1a1a1a; @include mq(sp) { height: auto; } } .l-header-logo { height: 130px; padding-top: 27px; border-bottom: 4px solid key-color(pink02); @include mq(sp) { height: 67px; padding: 14px 16px; border-bottom: 2px solid key-color(pink02); } &__image { display: block; width: 267px; margin: 0 auto; @include mq(sp) { width: 133px; margin: 0; } img { vertical-align: bottom; width: 100%; } } } .l-top-text { padding-bottom: 16px; background-color: #f5f5f5; @include mq(tb) { padding: 0 16px 16px; } @include mq(sp) { padding: 8px 16px; } p { width: 960px; margin: 0 auto; color: text-color(base); font-size: 1.4rem; line-height: 1; @include mq(tb) { width: 100%; } @include mq(sp) { margin: auto; font-size: 1.2rem; line-height: 1.5; } } } 2-4. _footer.scss 共通のフッターのスタイルをまとめたファイル。プロジェクト毎に必要に応じて編集。 _footer.scss #l-footer { max-width: 100%; background-color: #1a1a1a; } .l-footer-conainer { max-width: 1000px; margin: 0 auto; padding: 48px 0 24px; @include mq(tb) { padding: 48px 16px 24px; } @include mq(sp) { width: 100%; padding: 68px 0 24px; border-top: 4px solid key-color(pink02); } } .l-footer-logo { display: block; width: 160px; margin-bottom: 20px; @include mq(sp) { width: 120px; margin: 0 auto; } img { vertical-align: bottom; width: 100%; } } .l-footer-links { display: flex; flex-wrap: wrap; margin-bottom: 20px; @include mq(sp) { margin: 24px 0; // border: 2px solid #fff; } a, span { color: #fff; font-size: 13px; line-height: 24px; } a { @include mq(sp) { width: 50%; height: 58px; padding: calc(33px / 2) 0; border-color: #fff; border-style: solid; font-size: 1.2rem; text-align: center; line-height: 24px; } } span { padding: 0 4px; @include mq(sp) { display: none; } } } .l-footer-copyright { @include mq(sp) { text-align: center; } a { color: #fff; font-size: 1.4rem; line-height: 1; @include mq(sp) { font-size: 1.2rem; } } } 3. object プロジェクト毎や再利用可能など細かいスタイルを保存するディレクトリ。配下にcomponent, project, utilityの3つのディレクトリをもつ。 component :いくつかのページで共通するモジュール project :ページやレイアウト毎に固有のモジュールをまとめるファイル utility :強制的に適用するスタイル 4. component いくつかのページで共通するモジュール button、link、error、breadcrumbなど cssのセレクタは冒頭にc-を付けて記述していく。 4-1. _btn.scss _btn.scss .c-btn { position: relative; display: block; width: 376px; height: 52px; margin: 0 auto; background-color: #fff; border: 2px solid #333; border-radius: 26px; color: text-color(base); font-size: 1.6rem; font-weight: bold; text-align: center; line-height: 48px; transition: all .25s; &__arrow { position: absolute; top: 50%; right: 18px; width: 20px; height: 20px; margin-top: -10px; background-color: key-color(pink01); border-radius: 50%; @include mq(sp) { right: 16px; } &::before { content: ''; display: block; position: absolute; top: 0; bottom: 0; left: 0; right: 3px; width: 6px; height: 6px; margin: auto; border-top: 1px solid #fff; border-right: 1px solid #fff; transform: rotate(45deg); } } &:hover { background-color: #333; color: text-color(white); } @include mq(sp) { width: 264px; height: 40px; border: 2px solid #333; border-radius: 20px; font-size: 1.4rem; line-height: 36px; } } .c-btn-to-top { position: fixed; z-index: 5; right: 20px; bottom: 50px; width: 40px; height: 40px; background-color: #373737; transition: opacity 0.3s cubic-bezier(.13, .78, .38, .98); border-radius: 50%; cursor: pointer; @include mq(sp) { right: 16px; bottom: 16px; } &:hover { opacity: .5; } &::before { content: ''; position: absolute; top: 50%; left: 50%; display: block; width: 10px; height: 10px; margin-top: -3px; margin-left: -5px; border-width: 0; border-top: 2px solid #fff; border-left: 2px solid #fff; transform: rotate(45deg); } } 4-2. _breadcrumb.scss _breadcrumb.scss .c-breadcrumb { padding: 16px 0; background-color: #f5f5f5; @include mq(tb) { padding: 16px; } @include mq(sp) { overflow: scroll; white-space: nowrap; padding: 8px 16px; background-color: #fff; } &--narrow { background-color: #fff; .c-breadcrumb-list { width: 640px; @include mq(sp) { width: 100%; } } } } .c-breadcrumb-list { width: 960px; margin: 0 auto; @include mq(tb) { width: 100%; } &__item { position: relative; display: inline-block; color: text-color(link02); font-size: 1.3rem; @include mq(sp) { padding-right: 18px; font-size: 1.2rem; } &:not(:last-child) { padding-right: 18px; &::after { content: ''; display: block; position: absolute; top: 50%; right: 6px; width: 8px; height: 8px; margin-top: -5px; border-top: 1px solid #666; border-right: 1px solid #666; transform: rotate(45deg); @include mq(sp) { width: 6px; height: 6px; margin-top: -4px; } } } a { color: text-color(link02); &:hover { color: text-color(link02-hover); text-decoration: underline; } } } } 4-3. _error.scss _error.scss .p-error-header { margin: 32px 0 16px; font-size: 3rem; font-weight: bold; line-height: 1; @include mq(sp) { margin: 8px 0 16px; font-size: 1.7rem; } } .p-error-text { font-size: 1.7rem; line-height: 2; @include mq(sp) { font-size: 1.5rem; } } 4-4. _link.scss _link.scss .c-link01, .c-link02 { &:hover { text-decoration: underline; } } .c-link02 { color: link-color(link02); &:hover { color: link-color(link02-hover); } } 4-5. _pagenation.scss _pagenation.scss .c-pagination { margin: 24px 0 48px; @include mq(sp) { margin: 8px 0 24px; } } .c-pagination-list { display: flex; align-items: center; justify-content: center; } .c-pagination-item { display: inline-block; margin: 0 4px; background-color: #fff; border: 2px solid #333; border-radius: 50%; transition: .25s all; a { position: relative; display: block; width: 32px; height: 32px; color: text-color(base); font-size: 1.4rem; font-weight: bold; text-align: center; line-height: 32px; &:disabled { cursor: default; } } &:hover { background-color: #ddd; } // prev & next &.is-prev, &.is-next, &.is-ellipsis { a { font-size: 0; } } &.is-prev, &.is-next { a::before { content: ''; display: block; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 8px; height: 8px; margin: auto; border-top: 1px solid #222; border-left: 1px solid #222; } } &.is-prev { a::before { left: 4px; transform: rotate(-45deg); } } &.is-next { a::before { right: 4px; transform: rotate(135deg); } } // ellipsis &.is-ellipsis { .point-icon { position: absolute; top: 0; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; width: 13px; height: 3px; margin: auto; } .point { display: block; width: 3px; height: 3px; background-color: #222; border-radius: 50%; } &:hover { background-color: #fff; } } // current &.is-current { background-color: #333; a { color: key-color(pink01) !important; } } // disabled &.is-disabled { &.is-prev, &.is-next { background-color: #fff; } a { cursor: default; } } } 4-5. _title.scss _title.scss .c-title { margin-bottom: 24px; color: text-color(base); font-size: 3rem; font-weight: bold; line-height: 1; @include mq(sp) { margin-bottom: 16px; font-size: 2.2rem; } } .c-title-new-article { position: relative; margin-bottom: 24px; padding-bottom: 14px; color: text-color(base); font-size: 2.6rem; font-weight: bold; line-height: 1; @include mq(sp) { margin-bottom: 16px; padding-bottom: 12px; font-size: 2rem; } &::before, &::after { content: ''; display: block; position: absolute; bottom: 0; left: 0; height: 6px; @include mq(sp) { height: 4px; } } &::before { width: 150px; background-color: key-color(pink01); @include mq(sp) { width: 100%; } } &::after { width: 36px; background-color: #222; @include mq(sp) { width: 66px; } } } など。 5. project ページやレイアウト毎に固有のモジュールをまとめるファイル。他のページで使わない。 ページやレイアウト毎にディレクトリを作成して編集。cssのセレクタは冒頭にp-を付けて記述していく。 6. utility 強制的に適用するスタイル(!importantがつくもの)。メディアクエリ毎のスタイルもまとめる。 _space.scss :marginとpaddingに関するスタイル _typography.scss :textに関するスタイル _display.scss :displayに関するスタイル cssのセレクタは冒頭にu-を付けて記述していく。 6-1. _space.scss marginとpaddingに関するスタイル。一定間隔のmarginとpaddingを用意する。間隔は_variable.scssで定義。 例えばu-mt8 でmargin-top: 8px !importantとなるセレクタを作成する。 _space.scss .u-mxa { margin-left: auto !important; margin-right: auto !important; } @each $space in $spaces { // margin .u-m#{ $space } { margin: #{ $space }px !important; } .u-mx#{ $space } { margin-left: #{ $space }px !important; margin-right: #{ $space }px !important; } .u-my#{ $space } { margin-top: #{ $space }px !important; margin-bottom: #{ $space }px !important; } .u-mt#{ $space } { margin-top: #{ $space }px !important; } .u-mb#{ $space } { margin-bottom: #{ $space }px !important; } .u-ml#{ $space } { margin-left: #{ $space }px !important; } .u-mr#{ $space } { margin-right: #{ $space }px !important; } // padding .u-p#{ $space } { padding: #{ $space }px !important; } .u-px#{ $space } { padding-left: #{ $space }px !important; padding-right: #{ $space }px !important; } .u-py#{ $space } { padding-top: #{ $space }px; padding-bottom: #{ $space }px !important; } .u-pt#{ $space } { padding-top: #{ $space }px !important; } .u-pb#{ $space } { padding-bottom: #{ $space }px !important; } .u-pl#{ $space } { padding-left: #{ $space }px !important; } .u-pr#{ $space } { padding-right: #{ $space }px !important; } } @each $size in $sizes { @include mq($size) { .u-mxa-#{ $size } { margin-left: auto; margin-right: auto; } @each $space in $spaces { // margin .u-m#{ $space }-#{ $size } { margin: #{ $space }px !important; } .u-mx#{ $space }-#{ $size } { margin-left: #{ $space }px !important; margin-right: #{ $space }px !important; } .u-my#{ $space }-#{ $size } { margin-top: #{ $space }px !important; margin-bottom: #{ $space }px !important; } .u-mt#{ $space }-#{ $size } { margin-top: #{ $space }px !important; } .u-mb#{ $space }-#{ $size } { margin-bottom: #{ $space }px !important; } .u-ml#{ $space }-#{ $size } { margin-left: #{ $space }px !important; } .u-mr#{ $space }-#{ $size } { margin-right: #{ $space }px !important; } // padding .u-p#{ $space }-#{ $size } { padding: #{ $space }px !important; } .u-px#{ $space }-#{ $size } { padding-left: #{ $space }px !important; padding-right: #{ $space }px !important; } .u-py#{ $space }-#{ $size } { padding-top: #{ $space }px !important; padding-bottom: #{ $space }px !important; } .u-pt#{ $space }-#{ $size } { padding-top: #{ $space }px !important; } .u-pb#{ $space }-#{ $size } { padding-bottom: #{ $space }px !important; } .u-pl#{ $space }-#{ $size } { padding-left: #{ $space }px !important; } .u-pr#{ $space }-#{ $size } { padding-right: #{ $space }px !important; } } } } @eachを使うと指定した変数の要素を一つずつ抜き出す処理になる。間隔は_variable.scssで定義。 _variable.scss // space $spaces: 0, 8, 16, 24, 32, 40; 基本的には8の倍数の間隔を使用。 6-2. _typography.scss textに関するスタイル。font-weightやtext-alignなどのスタイルを定義している。 _typography.scss // font weight .u-fwn { font-weight: normal !important; } .u-fwb { font-weight: bold !important; } // text align .u-tac { text-align: center !important; } .u-tal { text-align: left !important; } .u-tar { text-align: right !important; } // text decoration .u-underline { text-decoration: underline !important; } // other .u-text-truncate, .u-text-clip { overflow: hidden !important; white-space: nowrap !important; } .u-text-truncate { text-overflow: ellipsis !important; } .u-text-clip { text-overflow: clip !important; } // line-clamp .u-clamp1, .u-clamp2, .u-clamp3, .u-clamp4 { overflow: hidden !important; text-overflow: ellipsis !important; display: -webkit-box !important; -webkit-box-orient: vertical !important; } .u-clamp1 { -webkit-line-clamp: 1 !important; } .u-clamp2 { -webkit-line-clamp: 2 !important; } .u-clamp3 { -webkit-line-clamp: 3 !important; } .u-clamp4 { -webkit-line-clamp: 4 !important; } // font size @each $fontSize in $fontSizes { .u-fs#{$fontSize} { font-size: #{$fontSize / 10}rem !important; } } @each $size in $sizes { @include mq($size) { @each $fontSize in $fontSizes { .u-fs-#{$size}-#{$fontSize} { font-size: #{$fontSize / 10}rem !important; } } } } フォントサイズやメディアクエリ用のサイズは_variable.scssで定義している。メディアクエリは_mixin@scssで定義。 _variable.scss // size $sizes: tb, sp; // font size $fontSizes: 10, 12, 14, 16, 18, 20, 22, 24, 26, 28; 6-3. _display.scss displayに関するスタイル。 _display.scss .u-dn { display: none !important; } .u-db { display: block !important; } .u-dib { display: inline-block !important; } .u-df { display: flex !important; } @each $size in $sizes { @include mq($size) { .u-dn-#{$size} { display: none !important; } .u-db-#{$size} { display: block !important; } .u-dib-#{$size} { display: inline-block !important; } .u-df-#{$size} { display: flex !important; } } } メディアクエリ用のサイズは_variable.scssで定義している。メディアクエリは_mixin@scssで定義。 _variable.scss // size $sizes: tb, sp; 7. コンパイル用のファイル 実際にコンパイルするファイルは以下になる。(resources > sass直下においた_のないファイルが該当) ├ common_inview.scss 全体で共通のファーストビュー用のスタイル。 ├ common_overview.scss 全体で共通のファーストビュー以外のスタイル。 ├ top_inview.scss トップページ固有のファーストビュー用のスタイル。 ├ top_overview.scss トップページ固有のファーストビュー以外のスタイル。 ├ (ページ名)_inview.scss ├ (ページ名)_overview.scss 7-1. inviewとoverview 共通のスタイルやページ毎のスタイルをinviewとoverviewの2つに分けている。 クリティカルCSSの考え方で、 ・inviewにはファーストビューで必要なスタイルを記述し、headタグの中でstyleタグで埋め込む。 ・overviewはファーストビュー以外で必要なスタイルを記述し、body閉じタグの前でlinkタグで読み込む。 これをすることでレンダリングブロックを回避し、ページの描画速度を改善することができる。 (補足)クリティカルCSSとは?使い方について 7-2. common_inview.scss 全体で共通となるファーストビューで必要なスタイルをまとめたファイル。 common_inview.scss @charset 'utf-8'; // foundation @import "foundation/variable"; @import "foundation/mixin"; @import "foundation/normalize"; @import "foundation/base"; // layout @import 'layout/grid/grid'; @import "layout/header"; @import "layout/container"; // object - component @import "object/component/breadcrumb"; @import "object/component/title"; @import "object/component/btn"; @import "object/component/link"; @import "object/component/pagenation"; @import "object/component/error"; // object - project // object - utility @import "object/utility/display"; @import "object/utility/space"; @import "object/utility/typography"; 7-3. common_overview.scss 全体で共通となるファーストビュー以外で必要なスタイルをまとめたファイル。 common_oveview.scss @charset 'utf-8'; // foundation @import "foundation/variable"; @import "foundation/mixin"; // layout @import "layout/footer"; variableとmixinはコンパイル時に必要となるファイル。 7-4. 補足 必要に応じて、ページ毎にページ名_inview、ページ名_overviewを作成する。 レイアウトのパターン数が多い場合は管理が大変になるため、クリティカルCSSではなく、コンパイル用にapplication.scssの1ファイルのみとする場合もある。 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cordovaの画面を固定サイズで実装する方法

固定の画面サイズで実装されているWebアプリをCordova 10に移植する場合の実装方法です。 ※CordovaはAndroidのみです。iOSは使用していません。ですが環境に限らず同じ方法は使えるはずです。 例えば300x400の固定サイズで実装したWebアプリがあるとします。 それをCordova上でスマホの端末の画面いっぱいに拡大表示することで、固定レイアウトのままAndroidアプリを作ってしまう方法です。Webアプリ移植時の変更を最小限にすることができます。 固定幅で作りたいだけならviewportを使う方法もありますが、幅も高さも画面からはみ出ないように柔軟に拡大するためJavaScriptで実装しました。 拡大表示する方法 CSSのtransformを使います。 以下のような記述をすると要素全体を拡大表示できることを利用します。 /* 150%に拡大する場合の例 */ transform: translate(25%, 25%) scale(1.5, 1.5); これをJavaScriptで動的に比率を計算して行います。 以下はメインformを画面サイズに合わせて拡大する部分のコードです。(記事の最後に全ソースがあります。) ※Webアプリのサイズが300x400(余白を入れると320x400)の場合のコードです。 ※formでなくてもdiv等でも同じやり方で拡大できます。 // 画面サイズに合わせて拡大 var windowWidth = (window.innerWidth || document.documentElement.clientWidth || 0); var windowHeight = (window.innerHeight || document.documentElement.clientHeight || 0); let percent = Math.floor(100 * windowWidth / 320); if (windowWidth > windowHeight) { percent = Math.min(percent, Math.floor(100 * windowHeight / 400)); } let scale = percent / 100; let translate = "" + ((percent - 100) / 2) + "%"; if (scale > 1) { mScale = scale; // グローバル変数に拡大率を保存しておく ※後で説明 document.forms[0].style.transform = "translate(" + translate + ", " + translate + ") " + "scale(" + scale + ", " + scale + ")"; } 固定サイズ座標取得方法 タップした位置の座標は固定サイズの仮想的な座標とはことなるので、マウスの座標のようにタップ位置を取得したい場合は座標変換が必要になります。 以下の部分が拡大表示したときの拡大率を使って座標を変換する部分のコードです。(記事の最後に全ソースがあります。) // イベントでの固定サイズ座標取得サンプル let getTouchPos = function(toucheInfo) { let orgX = toucheInfo.pageX; let orgY = toucheInfo.pageY; // ※mScale: 拡大表示したときの拡大率 // ※mAdjustX,mAdjustY: 基準位置(左上)の実際の座標 let x = (toucheInfo.pageX - mAdjustX) / mScale; let y = (toucheInfo.pageY - mAdjustY) / mScale; return { orgX, orgY, x, y }; }; document.addEventListener("touchmove", function(){ event.preventDefault(); // デフォルトのイベントを禁止する let pos = getTouchPos(event.touches[0]); // TODO 何かの処理 // ※pos.x, pos.yで固定サイズの座標が取得できます。 }, passiveSupported ? { passive: false } : false); 実際のCordovaのサンプルコード 画面を固定サイズ化(拡大)するサンプルコードを紹介します。 Webアプリのメイン領域を300x300の固定サイズで実装する場合のコードです。 Cordova(10.0)のindex.htmlに上書きすればサンプルの確認ができます。 index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'"/> <meta name="format-detection" content="telephone=no"> <meta name="msapplication-tap-highlight" content="no"> <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"> <meta name="color-scheme" content="light dark"> <link rel="stylesheet" href="css/index.css"> <title>固定レイアウト画面サンプル</title> <script> window.onerror = function(msg, uri, line) { alert(msg + uri + line); }; var mAdjustX = 0; var mAdjustY = 0; var mScale = 1; // Passive eventサポート有無のチェック var passiveSupported = false; try { window.addEventListener("test", null, Object.defineProperty({}, "passive", { get: function() { passiveSupported = true; } })); } catch(err) {} // ------------------------------------------------------------------------------------------------ // 初期化処理 // ------------------------------------------------------------------------------------------------ function initialize() { // フォーム表示によりずれる座標を調整する if (document.mainForm.offsetLeft) { mAdjustX = document.mainForm.offsetLeft; mAdjustY = document.mainForm.offsetTop; } else { mAdjustX = 0; mAdjustY = 0; } // イベントでの固定サイズ座標取得サンプル let getTouchPos = function(toucheInfo) { let orgX = toucheInfo.pageX; let orgY = toucheInfo.pageY; let x = (toucheInfo.pageX - mAdjustX) / mScale; let y = (toucheInfo.pageY - mAdjustY) / mScale; return { orgX, orgY, x, y }; }; let getMousePos = function(event2, event) { let orgX, orgY, x, y; if (event2.toString() == "[object MouseEvent]") { orgX = event2.clientX; orgY = event2.clientY; x = (event2.clientX - mAdjustX) / mScale; y = (event2.clientY - mAdjustY) / mScale; } else if(event) { orgX = event.clientX; orgY = event.clientY; x = (event.clientX - mAdjustX) / mScale; y = (event.clientY - mAdjustY) / mScale; } return { orgX, orgY, x, y }; }; document.addEventListener("touchstart", function(){ let pos = getTouchPos(event.touches[0]); // TODO 何かの処理 }, passiveSupported ? { passive: false } : false); document.addEventListener("touchend", function(){ let pos = getTouchPos(event.changedTouches[0]); // TODO 何かの処理 }, passiveSupported ? { passive: false } : false); document.addEventListener("touchmove", function(){ event.preventDefault(); // デフォルトのイベントを禁止する let pos = getTouchPos(event.touches[0]); // TODO 何かの処理 el("info").innerText = "本当の座標:(" + pos.orgX + "," + pos.orgY + ") 固定サイズ座標:(" + Math.floor(pos.x) + "," + Math.floor(pos.y) + ")"; }, passiveSupported ? { passive: false } : false); document.addEventListener("mousedown", function(event2){ let pos = getMousePos(event2, event); // TODO 何かの処理 }, false); document.addEventListener("mouseup", function(event2){ let pos = getMousePos(event2, event); // TODO 何かの処理 }, false); document.addEventListener("mousemove", function(event2){ let pos = getMousePos(event2, event); // TODO 何かの処理 el("info").innerText = "本当の座標:(" + pos.orgX + "," + pos.orgY + ") 固定サイズ座標:(" + Math.floor(pos.x) + "," + Math.floor(pos.y) + ")"; }, false); // 画面サイズに合わせて調整 var windowWidth = (window.innerWidth || document.documentElement.clientWidth || 0); var windowHeight = (window.innerHeight || document.documentElement.clientHeight || 0); let percent = Math.floor(100 * windowWidth / 320); if (windowWidth > windowHeight) { percent = Math.min(percent, Math.floor(100 * windowHeight / 400)); } let scale = percent / 100; let translate = "" + ((percent - 100) / 2) + "%"; if (scale > 1) { mScale = scale; document.forms[0].style.transform = "translate(" + translate + ", " + translate + ") " + "scale(" + scale + ", " + scale + ")"; } let gameScreen = el("gameScreen") let wallWidth = (windowWidth - gameScreen.getBoundingClientRect().width) / 2; el("mainDiv").style.paddingLeft = "" + wallWidth + "px"; mAdjustX = wallWidth; mAdjustY += el("scoreArea").getBoundingClientRect().height; } // ------------------------------------------------------------------------------------------------ // HTMLエレメント取得 // ------------------------------------------------------------------------------------------------ function el(strId) { return document.getElementById(strId); } </script> <style> body { font-family: sans-serif; overflow-y: hidden; } * { user-select: none; -ms-user-select:none; -moz-user-select:none; -webkit-user-select: none; -webkit-touch-callout: none; } #mainDiv { background-color: #bbbbff; text-transform: none; } .label { display: inline-block; text-transform: none; } </style> </head> <body onload="initialize();"> <!-- メイン --> <div id="mainDiv" style="width:100%; height:100%;"> <form name="mainForm" style="position:relative; width:100%; height:100%;" onsubmit="return false;"> <!-- 情報表示 --> <div> <div id="scoreArea" style="height:36px; color:#000080; font-weight:bold;"> <div style="font-size:100%; margin-top:2px; line-height:17px;"> <div class="label">TODO 情報表示エリア1</div><br> <div class="label">スコアの表示等</div> </div> </div> </div> <!-- スクリーン表示 --> <div> <div id="gameScreen" style="width:300px; height:300px; position:relative; background-color:#cccccc;"> TODO ここは300x300の固定サイズで実装可能 <div style="position:absolute; width:100px; height:100px; top: 50px; left: 50px; background:green; ">top: 50px;<br>left: 50px;</div> <div style="position:absolute; width:100px; height:100px; top:100px; left:100px; background:yellow;">top:100px;<br>left:100px;</div> <div style="position:absolute; width:100px; height:100px; top:150px; left:150px; background:red; ">top:150px;<br>left:150px;</div> </div> </div> <!-- 情報表示2 --> <div> <div id="scoreArea2" style="height:36px; color:#000080; font-weight:bold;"> <div style="font-size:80%; margin-top:2px; opacity:0.5;"> <div class="label" style="font-size:90%;">TODO 情報表示エリア2</div><br> <div class="label" id="info">スコア以外の表示等</div> </div> </div> </div> </form> </div> <script src="cordova.js"></script> <script src="js/index.js"></script> </body> </html> 実際にアプリを移植した例 実際に画面固定サイズで実装していたWebアプリ(ブロック崩しゲーム)をCordovaに移植してAndroidアプリを作成しました。 「HRGシンプルブロック崩し」としてGoogle Playで公開しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む