HTML5Experts.jp

とてもHackable!Styling Atom(Editor)─Frontrend Conference

本記事は、2015/2/21に行われた「Frontrend Conference」のファイナルセッション「Styling Atom(Editor)」の内容を紹介します。

オーバービュー

スピーカーはスイス生まれで、現在札幌で受託開発を行っている、Simon(ニックネーム:Simurai)さん、逐次通訳をHTML5 Experts.jpのエキスパートである斉藤祐也さんが努めました。

昨今、様々な企業サイトでのCSSの利用方法が公開されるようになってきました。CSS-Tricks(http://css-tricks.com/css/)に代表的なサイトの一覧が紹介されています。このセッションについても、CSS-Tricksに習って、Atom EditorでどのようにCSSが利用されているかを紹介します。

尚、本記事は、セッションの内容をそのままレポートにしているのではなく、Simuraiさんのセッション内容を基に私の方で再構成した、イベントレポートとなっています。

Atom Editorとは

Atom Editorは、GitHubが中心となりオープンソースで開発されているhackable text editorです。

引用元:https://atom.io/


Atom EditorはWindowsやMac上で動作するデスクトップアプリケーションであり、普通にインストールして利用することができます。しかし、内部的には、HTML/CSS/JavaScriptで全て実装されていて、いわゆるハイブリッドアプリケーションになっています。

特徴は以下のとおり。

Atom Shellについて

Atom ShellはChromeのオープンソースプロジェクトであるChromiumと、Node.jsのForkプロジェクトであるio.js(もともはNode.jsを利用していたが、最近変わった)で構成された、ネイティブアプリケーションプラットフォームです。 Atom Shellの概念図は以下のとおり。


BrowserというところがChromiumをベースにした部分であり、ネイティブアプリに必要なメニュー構築やダイアログ生成などを担当しています。また、Node.jsにてBrowserのネイティブAPIにアクセスできるインターフェースが用意されています。Renderer部分は、実際にアプリケーションの画面を描画したり、ロジックを組み込む部分であり、通常のWebアプリケーションと同じく、HTML、CSS、JavaScriptで実装することができます。JavaScriptについては、こちらもNode.jsが利用できます。

Atom Coreについて

Atom Shellの上にAtom Coreというメインのアプリケーションが存在します。Atom CoreはPackageというかたちで様々な機能を追加することができます。また、見た目についても、Themeというかたちで、様々に変更することが可能になっています。

引用元:Simurai氏セッション映像より


PackageやThemeの開発を含めたAtomの開発は、GitHub上で行われていて、だれでも自由にCommitすることができます。

ThemeでどのようにCSSが利用されているのか

さて、ここから、セッションの本題に入っていきます。

HEADエレメント

まずは、<head>エレメントの中をご紹介します。このソースはAtom CoreのベースとなるHTMLファイルを簡略化したものです。

<html>
    <head>

    &lt;style source-path="bootstrap.less"&gt;&lt;/style&gt;
    &lt;style source-path="atom.less"&gt;&lt;/style&gt;

    &lt;style source-path="tree-view.less" priority="0"&gt;&lt;/style&gt;
    &lt;style source-path="tabs.less" priority="0"&gt;&lt;/style&gt;
    &lt;style source-path="status-bar.less" priority="0"&gt;&lt;/style&gt;
    &lt;!-- Many many more packages --&gt;

    &lt;style source-path="ui-theme.less" priority="1"&gt;&lt;/style&gt;

    &lt;style source-path=".atom/style.less" priority="2"&gt;&lt;/style&gt;

&lt;/head&gt;
&lt;body&gt;&lt;/body&gt;

</html>

引用元:Simurai氏セッション資料


はじめに、bootstrap.less(normalize.css含む)を読み込み、次にCoreスタイルであるatom.less、Packageのlessファイル(tree-view.less等)を読み込み、そして、Themeを構成するui-styles.lessを読み込みます。実際には、それぞれのLESSファイルはCSSにプロセスされて挿入されることになります。

これは、Atom Editorの画面上でインスペクタ(開発者コンソール)を表示させて確認したところです。CSSのコードが挿入されていることがわかると思います。

UI Theme と Syntax Theme

次に、Themeについて詳しく見ていきます。Themeには、UIとSyntaxの2つがあります。UI Themeはアプリ全体のスタイルを規定し、Syntax Themeはエディタ部分のスタイルやコードのシンタックスハイライトなどを規定しています。

引用元:Simurai氏セッション資料


Themeのマークアップサンプルを見てみましょう。

<html>
    <head>
        <style source-path="ui-theme.less" priority="1"></style>
    </head>
    <body>

    &lt;ol class="tree-view"&gt;&lt;/ol&gt;
    &lt;ul class="tab-bar"&gt;&lt;/ul&gt;
    &lt;status-bar&gt;&lt;/status-bar&gt;

    &lt;atom-text-editor&gt;
        #shadow-root ----
        &lt;style source-path="syntax-theme.less"&gt;&lt;/style&gt;
        &lt;div class="gutter"&gt;&lt;/div&gt;
        &lt;div class="lines"&gt;&lt;/div&gt;
        #end-of-shadow-root ---
    &lt;/atom-text-editor&gt;

&lt;/body&gt;

</html>

引用元:Simurai氏セッション資料


ui-theme.lessとしてUI ThemeのLESSファイルを読み込みます。そして、UIに必要なパーツを配置していきます。このサンプルでは、tree-viewtab-barstatus-baratom-text-editorというパーツが記載していますが、実際にはもっとたくさんのパーツがあります。

そして、atom-text-editorエレメントの中では、エディタ部分を構成するためのパーツと、コードのシンタックスハイライトのためのSyntax ThemeのLESSファイルを読み込んでいます。

atom-text-editorエレメントはWeb Componentsの技術が利用されています。そのため、実際にはこのように#shadow-rootが挿入されます。Web Componentsを利用することで、UI ThemeとSyntax Themeを明確に分ける構造になっています。これによって、スタイルの衝突やクラス名の衝突を避けることができます。

shadow-rootは実際には、以下のように挿入されます。

ONE Theme

では、ONE Themeというテーマを例に、実際のThemeファイルの中身を少し見てみます。ONE Themeのソースコードはこちら(https://github.com/atom/one-dark-ui)で確認できます。

Atom Editorはテーマを読み込む際に、index.lessというファイルを最初に参照します。index.less@importで関係するスタイルファイルを順次読み込んでいきます。いわゆる、ヘッダーファイルのような役割を担っています。この例ではフラットに記載されていますが、書き方は自由です。

// Atom UI Theme: One

@import (reference) "styles/ui-variables"; @import (reference) "styles/ui-mixins"; @import (reference) "octicon-mixins";

@import "styles/atom"; @import "styles/badges"; @import "styles/buttons"; @import "styles/editor"; @import "styles/git"; @import "styles/lists"; @import "styles/messages"; @import "styles/nav"; @import "styles/overlays"; @import "styles/panels"; @import "styles/panes"; @import "styles/progress"; @import "styles/tabs"; @import "styles/text"; @import "styles/tooltips"; @import "styles/tree-view"; @import "styles/utilities";

@import "styles/settings"; @import "styles/core";

@import "styles/_deprecated";

スタイルファイルの中で注目すべきところは、カラーコードがハードコードされているわけではなく、全て変数として切りだされていることです。以下の例であれば、@tab-text-colorなどがそれに当たります。


: :

.tab { position: relative; top: @tab-top-padding; max-width: @tab-max-width; min-width: @tab-min-width; height: @tab-height; line-height: @tab-height; padding: 0; margin: 0; color: @tab-text-color; background: @tab-background-color; border-right: @tab-border; opacity: @tab-inactive-transparency; transition: opacity .3s; : :

切り出されたカラーコードは、ui-variables.lessというファイルにまとめて記述されています。


: :

// Component Colors -------------------------------------

@app-background-color: darken(@level-3-color, 2%);

@tree-view-background-color: @level-3-color; @tree-view-border-color: @base-border-color;

@tab-background-color: @level-3-color; @tab-background-color-active: @level-2-color; @tab-bar-background-color: @level-3-color; @tab-bar-border-color: @base-border-color; @tab-border-color: @base-border-color;

: :

これらの色情報同士は互いに連携。ある1箇所を変更すると関係する箇所が合わせて変更されると共に、色同士の関係性を見て、一体感のある色調になるように自動的に調整されるようになっています。

@import "syntax-variables"

: :

@ui-a: hsl(252, 11%, 18%); // fallback @ui-a: @syntax-background-color;

// Goal: use @syntax-background-color if it's dark enough, otherwise use same hue but stay dark // The light up by 100% is done to trick contrast() into picking one of 2 dark colors @ui-a-h: hue(@ui-a); @ui-a-s: min( saturation(@ui-a), 12%); @ui-a-l: luma(@ui-a) + 100%; // (1) light up @ui-a-light: hsl(@ui-a-h, @ui-a-s, @ui-a-l); // (2) flashed color @ui-a-color: contrast(@ui-a-light, @ui-a, hsl(@ui-a-h, @ui-a-s, 24%) ); // (3) use @ui-a if darker than 24%

: :

また、ui-variables.lessでは、Atom Editorで標準定義されているシンタックスハイライトのための色情報を、syntax-variablesから読み込むことで、@syntax-background-colorという変数をこのテーマのシンタックスハイライトカラーとして利用しています。

Style Guide

Atom Editorでは、だれでも、EditorのThemeを作ることが可能です。新しく作ってもいいし、既存のThemeをフォークしても構いません。Themeを新作る際の便利な機能として、Style GuideというPackageが標準搭載されています。

Style Guideを利用することで、Themeの中で規定されている色情報やClassの定義など全てを、視覚的にリアルタイムに確認することができます。

<起動方法> Packages > StyleGuide > Show

Themeの作成やカスタマイズにはなくてはならないツールです。

Atom Editorの悪い部分

冒頭に紹介したCSS-Tricksのブログでは、よい点だけではなく、問題点なども合わせて取り上げられているため、とても参考になります。Atom Editorについても、それに習って、あえて悪い部分を取り上げてみます。

1. どこにソースファイルがあるか分からない

Atom Editorのインスペクタを表示するとわかると思いますが、CSSそのものへのリンクはありません。これは、LESSを動的にCSSに変換しているので、そもそもCSSファイルが存在しないためです。

また、以下のように、同じセレクタが複数存在するところがあります。それぞれPackageとThemeで定義されているのですが、どちらがどちらに定義されているのか、インスペクタを見ただけではわかりません。これは、Source mapを使えば解決できるかもしれませんが、現在のAtom Editorには含まれていません。

2. CSSのネストが深い

上記画像を見ると、Classのネストが3階層になっている事がわかると思います。このように、ネストが深い部分が多々あります。そのため、特定の属性を上書きしたい場合などは、Classのセレクタをネストの数だけ記載する必要が出てきます。

これは、セレクタを以下のように記載することで解決することができます。


// SUIT ----

.Tabs {} .Tabs-item {} .Tabs-title { color: white; }

// Benefit ----

.Tabs-title { color: red;

}

引用元:Simurai氏セッション資料


このようにセレクタを記載することで、以下の様な利点が生まれます。

3. Atom Editor Version 1.0ローンチ間近…

ではなぜ、Atom EditorでこのようなSUIT CSSやBEM CSSなどの設計ルールを取り入れないのか。実際に、GitHubのIssueでもそのような問い合わせがきています。

取り入れない理由は、Atom Editor Version 1.0のローンチが間近に迫っており、近々仕様凍結が予定されているためです。仕様が凍結されると、Classの命名規則含めてAPI仕様の大幅な変更ができなくなります。そのため、SUITやBEMなどの導入はVersion 2.0に向けて行う必要が出てきているのです。

Atom Editorの未来

Atom Editorに将来実装したい機能の1つとして、UIテーマのコントラストを周辺光に合わせて自動的に調整する機能が考えられています。

例えば、部屋の明かりが暗い時は、このように見やすいThemeですが…

引用元:Simurai氏セッション映像より


部屋が明るくなると、画面への光の映り込みが起こり、見難くなりますよね。

引用元:Simurai氏セッション映像より


これを解決したいのです。

周辺光に合わせたUIテーマの自動調整は、W3Cで標準化が進んでいるlight-level MediaQueryを利用することで、実現することができると考えています。

// default
body {
    color: hsl(0,0%,70%);
}

// gets dark @media {light-level: dim} { body { color: hsl(0,0%,48%); } }

// gets bright @media {light-level: washed} { body { color: hsl(0,0%,100%); } }

// other pattern @media {light-level: washed}{ body { -webkit-filter: contrast(1,25) brightness(2); }

}

引用元:Simurai氏セッション映像より


このように記載することで、デバイスに搭載されている光学センサで周辺光を測定し、その値に応じてbodyエレメントの明るさを調整することができます。

また、明るくなった場合の別の調整手段として(上記other pattern参照)、contrastbrightnessを利用して、画面全体のコントラストや明るさを一気に調整することもできます。しかしながら、これはパフォーマンスがよくない可能性もあるので、実装する際には注意が必要です。

まとめ

Simurai氏のセッションは、Atom Editorが『なぜhackable text editorなのか?』を、わかりやすく伝える面白い内容でした。興味を持たれた方は、是非、Atom Editorを自分色にカスタマイズしてみてください!

もっと詳しくAtom Editorについて聞きたい!知りたい!という方は、Twitterなどでご本人に質問してみるとよいでしょう。



Frontrend Conference特集はまだまだ続きます!

イベント動画

イベントの模様はYoutubeで公開されています。よろしければ、ご覧ください。