右矢印キーを押すと左にカーソルがうつる不可思議なテキストボックスについて


前の会社での話。

実は、前の会社を辞めてからも9月は特別に週一回行っていまして、自分がある程度関わったプログラムのバグ修正なんかをしていました(ほとんど、自分が関わったところではないところに時間を使いましたが)。

そんな中、昨年退職した上司が作成したあるウェブページのテキストボックスが変な挙動をしていました。

そのテキストボックスには、数値が入っていて、右寄せになっていました。その時は特別深く考えたわけではないのですが、CSSのtext-alignでrightを指定しているんだろうなとは思いました。

それはいいのですが、どうも入力するとおかしなことになります。

IEだと右矢印キーを押すと左にカーソルが移動し、左矢印キーを押すと右にカーソルが移動します。よくわからないけど、IEのバグかなと思って試しにChromeで見てみると、なんとChromeでは一番右にカーソルをうつして入力すると左側に文字が追加され、逆に一番左にカーソルをうつして入力すると右側に文字が追加されます。

初めての減少に思わずポカンとしてしまったのですが、多分、keydownでイベントを発生させていて何かやらかしているのだろうと思い調べてみました。すると、予想通り、数値のみしか入力させない記述がしてありました(参考:HTMLのテキストボックスを、できるかぎり半角数値のキー入力のみにする | while(isプログラマ))。

というわけでいろいろ変更してみたのですが、全く変化がありません。そして、試しにkeydownのイベントを無くしてみましたが、全く変化がありませんでした。正直、わけが分かりませんでした。

とりあえず、一から考え直そうと思って開発者ツールで対象のテキストボックスを選択し、右側のサイドバーを見たところ、あると思ったものが無いことに気づきました。そう、『text-align:right』の記述がありませんでした。スクロールバーを上から下まで移動させて見てみたのですが、その記述がみあたりません。「右寄せになってるのになぜ?」もはやパニックに近い状態の自分でしたが、ふと見られない記述がありました。

『direction:rtl』

なんじゃこりゃ? と思って調べてみると、文章の記述方向の設定をしている記述ということが分かりました(参考:direction – CSS | MDN)。rtl は右から左……。まさか……。

この記述を無くしたら、カーソルが想定通りに動きました(もちろん、これだと左寄せになってしまうので、『text-align:right』を追加しておきました)。

とりあえず、同じようなテキストボックスを下記においておきます。valueの値は12345としています。こうすれば、『54321』と表示されるような気がしなくもないんですが、『12345』と表示されています。

というわけで、もし、矢印キーを押したら逆方向にカーソルが移動する場合は、この記述がないか疑ってください。そんなこと、滅多にないと思いますが……。

なお、「テキストボックスに『direction:rtl』の指定があればカーソルの動きがおかしくなる。ということを言いたいだけだろうに、前置きが長すぎ! そんなんだからブログ続かないんだろ!」なんてツッコミは受け付けておりません。むしろ、こう書いたことがセルフツッコミです。

画像の比率を保ったまま枠内に収めて縦横中央表示するCSS(IE8対応)


divタグなどの枠内に画像を入れる時、縦横中央表示にして、かつ、枠のサイズより大きければ枠に収まるように画像の比率は変えずに小さくしたいということがあると思います。というより、先日自分はそういう事態に遭遇しました。

まず、サイズの比率を保ったまま、枠内に収める方法ですが、いろいろ試行錯誤した結果、下記のようにするとうまくいくことが分かりました。

widthとheightは普通、デフォルトがautoなので指定しなくていい場合が多いのですが、autoじゃないと動かないため指定しています。

上記の記述だと、枠(この場合、imgタグの親要素)のサイズより大きければ、max-widthとmax-heightの指定により、それ以上のサイズを超えないようになるので、枠に収まってくれます。最初はてっきり、どちらも100%のサイズになってしまうのではないかと思ったのですが、どうやら大きい方にあわせて縮小されるようです。

次に、縦横中央表示の方法ですが、横は簡単です。親要素に『text-align:center』を指定してやればいいだけです。問題は、縦の中央表示。いろいろ調べてみると、:before擬似要素を使って下記のように書くと、縦横中央表示する方法があることが分かりました。

before擬似要素をinline-blockとし、縦方向の揃えをmiddleとしています。同じく画像のほうもmiddleとすることにより、どちらも縦中央表示になります。ただ、inline-blockにすると余計なスペースができてしまうので、そのスペースを無くすために、枠の要素にfont-size:0の指定をしました(参考:display: inline-block の隙間を詰める方法 | Soraxism)。

ちなみに、IE8には対応していませんが、画像をCSSのbackground-imageで指定し、background-sizeをcontainとすると、枠に収まるようになりますが、この場合、枠のサイズより小さければ画像が拡大して枠のサイズに合わせて表示するようになります(もちろん、そのほうがいいということもあると思います)。

なお、IE8対応しなくていいのであれば、フレックスボックスやtransformを使って縦中央表示できます。

フレックスボックス利用

transform利用

下記にサンプルリンクを載せておきます。background-size:containを使った結果、フレックスボックスを使った結果、transformを使った結果も載せています
フレームサイズ:100×150、画像サイズ:175×200
フレームサイズ:100×150、画像サイズ:200×175
フレームサイズ:175×200、画像サイズ:100×150
フレームサイズ:175×200、画像サイズ:150×100
サイズランダム

ios8にfloatバグがあるようだからFlexboxで対応してみた


先日、1年ほど前に仕事でiPad用に作ったサイトを触っていると、floatを利用した箇所が大きく崩れることがあることが分かった(いつもではないし、崩れ方も異なる)。

確か下記のようなCSSでした。

家に帰って実装してみて試してみると再現されなかったので違うかもしれませんが、とにかく上記のレイアウト指定ならリストは3列の並びになるはずなのに、3つ並んでる行もあれば2つしかない行もあるし1つしかない行もあったわけです。

調べてみたらiOS8のバグのようでした。
参考:iOS8でリストのレイアウトが崩れたら : のり記
参考:W3GさんはTwitterを使っています: “iOS8 SafariのCSSレンダリングが不安定化になるのは特定のJS実行下で発生する模様。pushStateでnth-childが効かなくなると。http://t.co/bO2Kasuyk3 他にもcliclイベント発火でfloatが無効されたりJSとの因果関係で不安定化する”

最初は、『display:inline-block』で対処するか。と思ったのだけど、試してみると全て2行表示になってしまった。inline-blockを指定した要素は改行すると隙間ができてしまうんですよね。対処方法はあるのは知ってるのですが(参考:inline-blockを並べた場合に発生する「隙間」を消去するCSS » INSPIRE TECH)、勉強がてらFlexboxを使ってみることにしました。

例えば先ほどのスタイル指定だと、下記のようにすれば同じレイアウトになります。

ただ、これだとちょっと古いブラウザだとレイアウトが崩れます。そこで、Flexboxの『flex-wrap』が指定してるかどうか調べたうえで、指定できるならFlexboxを、指定できないならfloatを指定することにしました。

CSS

JavaScript(jQuery使用)

実行結果:ios8でのfloatバグ対応

Flexboxは結構前から知ってはいたのですが、実装されてるブラウザも少なく、ころころ仕様も変わるもんだから利用を避けてたのですが、最近になって十分に使えるようになってきたようです(参考:これからのCSSレイアウトはFlexboxで決まり! | Webクリエイターボックス)。いろいろなプロパティがあってややこしいのですが、機会があればまた使ってみようと思います。

CSS3で追加されたcurrentColorキーワードを試してみた


先日、ブックオフのタッチでおトクなメンバーズが8月で利用できなくなると知り(参考:【BOOKOFF タッチでおトクなメンバーズ】サービス名称・内容変更について)、ブックオフに行きました。そこで2011年に発売された定価2800円のCSS3本の値札が700円、しかもその日は半額デイだったため350円で売られていたので思わず購入。まだほとんど読んでないのですが、パラパラめくっていると色の指定方法について書かれた項目に『currentColor』という値が書いてありました。

一瞬、「現在の色? それって何も指定しないのと同じじゃ……」と思ったのですが、よくよく読んでみると現在の要素の文字色を表す値ということが分かりました(参考:color value – CSS | MDN(currentColor キーワード))。

たまに文字色とボーダーの色を同じにするようなレイアウトのスタイルを記述することがありますが、そういう時に便利なキーワードですね。

というわけで試してみました。

HTML

CSS

実行結果:currentColorテスト

確かに、指定の色が、その要素の文字色と同じ色になっていることが分かります。覚えておきたいです。

ここから余談です。

先日、プロとして恥ずかしくない 新・WEBデザインの大原則を読みました。タイトルにWEBデザインとありますが、デザインだけでない、WEB制作について広範囲に書かれており、わかりやすかったので良書といえると思います。
ですが、一つだけ気になった点があります。その点を以下に引用します。CSSの基本について書かれた項目の一部です。
名前からも想像できる通り、colorは文字色(前景色)を、background-colorは背景色を指定するためのプロパティだ。
自分は、background-colorが背景色を表すのは一目見たら分かると思うのですが、colorプロパティは見ただけでは文字色を表すと分からないと思います。時々、疑問に思うんです。なんで、CSSを作った人は、文字色の指定するプロパティを、font-colorとかtext-colorという書き方にしなかったのだろうかと。
まあ、こんな疑問もつの自分だけかもしれないんですけどね。

CSSとJSで要素の背景にcanvas画像を設定する方法


WebKit系とFirefox限定です(IEでは利用できない)。

CSSのbackgroundプロパティにおいて、WebKit系のブラウザにはcanvas()関数、Firefoxではelement()関数という値が指定できます。canvas()関数は、canvasに描画したものを背景に設定できる関数で、element()関数は指定の要素を画像として扱い背景にすることができます(残念ながら、背景にしかできない)。

で、これに関連してWebKit系のブラウザのJavaScriptにはgetCSSCanvasContextメソッド、FirefoxにはmozSetImageElementメソッドというものが用意されています。これは、どちらもブラウザ上でcanvasを作成し、ブラウザ上にcanvasを描画せずにcanvas画像を背景に設定できる機能です(参考:[CSS3] (Webkit専用) CSSを用いて要素の背景にCanvasを指定する – YoheiM .NETCSSのelement()関数 – Weblog – Hail2u.net)。

関数が違うので、どちらも共通の指定でcanvasの背景画像を作成できるように関数を作ってみました。

この関数からえたコンテキストを利用すると、WebKit系でもFirefoxでも同じ処理で背景用canvasを取得できます。
利用例は以下のような感じ。

CSSは下記のように書きます。

というわけで、以下実行サンプルです。

正直、そこまで実用性があるわけではなさそうですが、こういうことができるという紹介。IEにも対応したい場合は、canvasのtoDataURLでBase64の画像データを取得して、それをJavaScriptを用いて要素の背景に設定するという方法でできそうです(というより、それでcanvasに対応している全てのブラウザに対応できる)。