20200208のCSSに関する記事は2件です。

特定要素の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/

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

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の組み合わせ、気軽に使えて、拡張も楽々でお気に入り。
得た知見は、以下の通り。

  • フィルタにすると、テンプレートを変更しないと内容が書き換わらない。
  • コンテキストプロセッサーを使うと、テンプレートへの埋め込み処理の以前に実行されるので、常に値が最新にできる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む