鶏口牛後な日々

心の赴くまま、やりたいことを仕事に。

stylusでcalcを使って自動で幅を設定しようとしたらうまくいかなかった

うまくいかなかったこと

単純なプラスはうまくいったのですが、マイナスがうまくいかず、マイナスに加えて割り算を組み合わせようとした場合も、うまく計算してくれませんでした。 ということで調べたことをまとめておきます。

単純なプラスするcalc(うまくいった)

width calc(100% + 60px)

難しく考える必要はなく、これでちゃんと描画されました。

単純なマイナスするcalc(うまくいかなかった)

calcで、スクリーンの横幅(100%)から、左右の20pxずつのマージンを引いた横幅を、ある枠に設定したい! とします。

width calc(100% - 40px)

でいいでしょう。と思いきや、ダメでした。

stylusでは、なにやら、 - が前に付くことで、変数だと勘違い?? したりするんだとか。
ということで、 - の前に、 \ (バックスラッシュ)をつけてあげるといいらしい。エスケープさせるということかな。(すんませんちゃんと調べてない、詳しくはご自身でお調べください)

width calc(100% \- 40px)

こうすれば、上手く効くようになりました。

引き算と割り算を同時に使うケース(うまくいかなかった)

135pxの横幅のものを、必ず画面の真ん中に配置したいという場合です。 入れ物に、 position: relative をつけ、配置したいものに、 postion: absolute をつけます。 そして、配置したいものの left に設定するものは、

left calc((100%-135px)/2)

で良いはず・・・
と思ったら!!

なんと、HTMLでレンダリングされたinspectを見たら、 calc((-35%)/2) と出ている・・・

なんでだ?? 違う違う!!!

これは、調べてみたらバグっぽかったです。

以下のように書いたら、思った通りに配置されました。

leftMargin = unquote('100% - 135px')
left 'calc((%s) / 2)' % leftMargin
  • leftMargin というのは、変数(自由に命名できる)を使っています。
  • % の後ろに leftMargin (変数)を指定することで、 %s に入れ込むことができました

このタイプについては、 - の前に、 \ (バックスラッシュ) つけてみてもダメで、やはり計算結果が変になったので注意が必要です。

stackoverflowでは2013年あたりの記事で書かれたものを参考にしましたが、2018年11月現在未だにこのやり方でないとうまくいかないようなので、stylus的に直す気は無いということでしょうか。

上下左右真ん中に配置したいケース

f:id:TACOSVilledge:20181108132308j:plain

基本的には、先ほどのケースと同じです。 図のように、丸を左のボックスAの真ん中に配置したい! という場合です。

ボックスAに position: relative をつけ、丸に position: absolute をつけますね。 そして、丸に topleft を設定する時に、 calc を使用したいわけです。 設置したい画像(=丸)の幅を、ボックスAの幅から引いて、二で割ると、丸の left に相当しますね。

  .A
    position relative
    display block
    flex-basis 30%
    float left
 
  .B
    position absolute
    background-color #fff
    diameter = 50px
    width diameter
    height diameter
    border-radius 'calc((%s)/2)' % diameter
    topMargin = unquote('100% - 50px')
    top 'calc((%s)/2)' % topMargin
    leftMargin = unquote('100% - 50px')
    left  'calc((%s)/2)' % leftMargin

注: Aflex-basis は、それだけではflexになってはくれず、その親に display: flex を入れておく必要があります。念のため。詳しくはそれについて書いたこちらの記事を参照のこと。

本当は、 topMargin および leftMargin50px と書いているところを diameter という変数を入れて、丸の直径 diameter を変えれば全て自動で変わるようにしたかったのですが、 unquote の中に calc を入れるとうまくいかなかったので、断念して、 50px とベタ書きした形になります。 せっかく変数が使えると思うと、もう少し複雑な計算式も書き込めるようにしてほしい、と思う一方で、レンダリングに時間がかかってしまうのかもしれないと思うので、できる範囲で使って行きます。

細かい間違えやすい点(補足)

ちなみに、

○ left  'calc((%s)/2)' % leftMargin

こうするべきところを

× left  'calc(%s/2)' % leftMargin

というように、分子をカッコでくくるのを忘れると、上手く効きませんでした。(chromeで確認)

さらに、

○ leftMargin = unquote('100% - 50px')

のところで、マイナス記号の間のスペースをなくしたところ、これも効きませんでした(同じくchromeで確認)

× leftMargin = unquote('100%-50px')