- 投稿日:2020-02-08T15:31:21+09:00
特定要素のwidth基準のサイズ指定 by css&js
vwは便利ですけど、画面全体の幅基準なので、responsiveに幅の変化する要素を基準にはできませんね。
以下はそれをjsで実現するものです。css:root{ --base1: 0; } .title-box{ position:relative; } .welcome{ font-size: calc(var(--base1) * 8vw); margin-top: calc(var(--base1) * 17vw); } .title{ font-size: calc(var(--base1) * 12vw); line-height: calc(var(--base1) * 12vw); margin-top: calc(var(--base1) * 3vw); }html<div data-calc-base="base1" class="title-box" > <div class="welcome">ようこそ!</div> <div class="title" >種子島へ!</div> <img src="/img/tanegasima/top.jpg" > </div>js$(window).on('load resize', ()=>{ $('[data-calc-base]').each(function(){ document.documentElement.style.setProperty( '--' + $(this).data('calc-base'), $(this).width() / $(window).width() ); }); });inspired by
https://flex-font.com/how_to/
- 投稿日:2020-02-08T10:27:52+09:00
FlaskでWebアプリ開発中にCSSが反映されない問題を解決する
FlaskでWebアプリを開発している。その際、WebブラウザにCSSがキャッシュされてしまう問題に、どう対処するか考えてみた。
HTML内でCSSをリンクする際、
style.css?v=12
などのように手動で、更新日時やバージョンを付け加えている場合がある。しかし、せっかくPythonを使っているので、これを自動で解決してもらいたい。模範解答
検索してみると模範解答は、以下のように、url_forを書き換えると良いという回答だ。
app.py@app.context_processor def override_url_for(): return dict(url_for=dated_url_for) def dated_url_for(endpoint, **values): if endpoint == 'static': filename = values.get('filename', None) if filename: file_path = os.path.join(app.root_path, endpoint, filename) values['q'] = int(os.stat(file_path).st_mtime) return url_for(endpoint, **values)そして、テンプレートでは、以下のようにリンクする
hoge.html<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">コンテキストプロセッサーの、url_forを上書きするテクニックだ。エンドポイントにstaticが指定された時に、ファイル更新日を付け加えるというテクニックだ。
ちなみに以下が元ネタの英語ページ。日本の他のブログでもこれを参考に紹介されていた。
(参考) https://stackoverflow.com/questions/21714653/flask-css-not-updatingこの回答に不満というか、Flaskのurl_forに不満
ただし、いつも思うのだが、静的なリンクを書くだけなのに、url_forを使うのは長い。手間だ。Flaskでは、静的ファイルを配置するのは
/static
以下とデフォルトで決まっているので、CSSを配置するパスも既に決まっているはず。つまり、静的ファイルを埋め込むだけなのに、url_forを使うのは、かなり面倒に感じる。そこで、手抜きして、以下のようにする方法を考えてみた。
手抜き回答 - 半分失敗の例
最初にフィルタを使う方法だ。
app.py@app.template_filter('staticfile') def staticfile_filter(fname): path = os.path.join(app.root_path, 'static', fname) mtime = str(int(os.stat(path).st_mtime)) return '/static/' + fname + '?v=' + str(mtime)テンプレートは以下のように書く。
hoge.html<link rel="stylesheet" type="text/css" href="{{ 'style.css' | staticfile }}">模範解答より、ずっとエレガントにできた。
とは言え、この方法では、テンプレートエンジンによって、HTMLがキャッシュされてしまっているため、瞬時にキャッシュが更新されないのが問題だ。それでも、一応、style.css?v=xxxのようになる。
手抜き回答 その2 context_processorを追加する
やはり、模範解答を咀嚼して、context_processorを利用するようにするのはどうかと考えた。
app.py@app.context_processor def add_staticfile(): def staticfile_cp(fname): path = os.path.join(app.root_path, 'static', fname) mtime = str(int(os.stat(path).st_mtime)) return '/static/' + fname + '?v=' + str(mtime) return dict(staticfile=staticfile_cp)そしてテンプレートは以下の感じ
hoge.html<link rel="stylesheet" type="text/css" href="{{ staticfile('style.css') }}">これなら、キャッシュされず、瞬時に値が反映されるし、それほど見た目が悪くないから良いかな?
所感
Flask + jinja2の組み合わせ、気軽に使えて、拡張も楽々でお気に入り。
得た知見は、以下の通り。
- フィルタにすると、テンプレートを変更しないと内容が書き換わらない。
- コンテキストプロセッサーを使うと、テンプレートへの埋め込み処理の以前に実行されるので、常に値が最新にできる。