🪂

CSS嫌いエンジニアの生存戦略~巨人の肩に乗りまくり~

2023/08/28に公開

このページを訪れた方へ

CSSが嫌い?それとも苦手?
この記事は、根本的なCSSへの苦手感を拭ったり、CSSを使えるようになるような記事ではありません。問題を解決しないし、"学び"としては嫌悪されるものです。フロントエンドエンジニアは曲がれ右してください。

他のCSS苦手なエンジニアは、どんなふうに開発してるんだろう?
という疑問を抱く方に向けて、少しでも参考や安心に繋がればいいなと思います。

なぜCSSが嫌い/苦手なの?

CSSが嫌いなエンジニアが多い理由を、勝手に考えてみたの記事を見て、だから私はCSSが苦手なのか、と納得しました。

  • エラーが出ない
  • プロパティの種類が多すぎる
  • 無効化や削除したいのに、なんのプロパティのせいなのかが分からない
    これがが私の苦手感の元でした。

どこのCSSがどんなふうに効いているのか?
が全くわからない。調べてやってみても、効かなかったり変に効いたり...
とにかく不明な点が多い。プロパティの種類も多いので難易度UP。
地道にモックアップをしても、結局身についてるのかよくわからない。
「とにかく今すぐモダンでいい感じの見た目を作りたい」
そんな時には巨人の肩に乗らせてもらおう。

Soliloquy Chat App

私の戦略を紹介するにあたり、例としてSoliloquy Chat Appを紹介します。
完成したUIはこんな感じ。
シンプルなChatの画面。「明日雨降れ!」など取り止めのないメッセージがチャット画面に反映されている
チャット画面に炎が上がっている様子

Tech Stack

こちらはとってもシンプルな静的Appです。

  • HTML
  • CSS
  • JavaScript
  • Render(デプロイ先)

詳しい開発経緯やApp内容については別記事へどうぞ。
https://zenn.dev/kiki_her/articles/fbe8cd2ec826d5
Githubはこちら

CSSどうしたの?

CodePenでお二方の先人のコードをお借りしました...!
最初は自分でやってみたものの、レスポンシブルで洗練されたデザインを...となると1からはとても無理。
UIコンポーネントライブラリを使いたい。React愛してる。

しかし、今回はVanillaでやると決めたので、自力でCSSを書くも断念。
CodePenで出会った偉大なるお二方のコードをお借りしました。

Codepen利用時の注意

Codepenに公開されているコードを自分のAppに取り入れる時には、以下のように引用元を表記する必要があります。

/* 
	Copyright (c) YEAR - AUTHORS NAME - URL TO ORIGINAL
	Released under the MIT license
*/

公開されている大抵のコードはMITライセンスが取り入れられているそうです。

取り入れ方

自分が作りたいものを固めたら、Codepenで作りたいものに近いコードを探します。
例えば、今回私は「Chat CSS」「Fire CSS」と調べました。
上記の検索ワードでヒットした中で、Simple Chat UI by Sajad Hashemianと、CSS Only Fire by Simon Goellnerを使用させていただきました。

では、手本にするコードを見つけたらどうするか?
8つのStepにして紹介します。

  1. 作りたいAppのテーマ色を決める(1~3色の組み合わせ)
  2. Codepenをコピー&ペースト
  3. CSSでカラーをテーマ色に変える
  4. HTMLで、自分のAppには不要な要素を削除する
  5. CSSで、削除した要素についていたclass等へのstyleを削除する
  6. HTMLに、さらに追加したい要素を追加する(Soliloquy Chat Appではポップアップを追加)
  7. Codepenで見つけたコードを組み合わせる場合は、既存のHTMLの要素にclassをつけて実装するか、新しくHTMLの要素を追加するか検討(今回はclassを追加し、JSでclassの切り替えを実施)
  8. JSを扱いやすいように、リファクタリングする

わかりやすい変更例として、JSコードを載せます。

オリジナルのJSコード

from Simple Chat UI by Sajad Hashemian

const msgerForm = get(".msger-inputarea");
const msgerInput = get(".msger-input");
const msgerChat = get(".msger-chat");

const BOT_MSGS = [
  "Hi, how are you?",
  "Ohh... I can't understand what you trying to say. Sorry!",
  "I like to play games... But I don't know how to play!",
  "Sorry if my answers are not relevant. :))",
  "I feel sleepy! :("
];

// Icons made by Freepik from www.flaticon.com
const BOT_IMG = "https://image.flaticon.com/icons/svg/327/327779.svg";
const PERSON_IMG = "https://image.flaticon.com/icons/svg/145/145867.svg";
const BOT_NAME = "BOT";
const PERSON_NAME = "Sajad";

msgerForm.addEventListener("submit", event => {
  event.preventDefault();

  const msgText = msgerInput.value;
  if (!msgText) return;

  appendMessage(PERSON_NAME, PERSON_IMG, "right", msgText);
  msgerInput.value = "";

  botResponse();
});

function appendMessage(name, img, side, text) {
  //   Simple solution for small apps
  const msgHTML = `
    <div class="msg ${side}-msg">
      <div class="msg-img" style="background-image: url(${img})"></div>

      <div class="msg-bubble">
        <div class="msg-info">
          <div class="msg-info-name">${name}</div>
          <div class="msg-info-time">${formatDate(new Date())}</div>
        </div>

        <div class="msg-text">${text}</div>
      </div>
    </div>
  `;

  msgerChat.insertAdjacentHTML("beforeend", msgHTML);
  msgerChat.scrollTop += 500;
}

function botResponse() {
  const r = random(0, BOT_MSGS.length - 1);
  const msgText = BOT_MSGS[r];
  const delay = msgText.split(" ").length * 100;

  setTimeout(() => {
    appendMessage(BOT_NAME, BOT_IMG, "left", msgText);
  }, delay);
}

// Utils
function get(selector, root = document) {
  return root.querySelector(selector);
}

function formatDate(date) {
  const h = "0" + date.getHours();
  const m = "0" + date.getMinutes();

  return `${h.slice(-2)}:${m.slice(-2)}`;
}

function random(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

リファクタリングしたJSコード

// 使わない関数は削除
const msgForm = document.getElementsByClassName("msger-inputarea");
const msgInput = document.getElementsByClassName("msger-input");
const msgChat = document.getElementsByClassName("msger-chat");
const main = document.getElementsByClassName("msger");
const title = document.getElementsByClassName("msger-header-title");


msgForm[0].addEventListener("submit", (e) => {
    e.preventDefault();
    const msgText = msgInput[0].value;
    if(!msgText) {
        return;
    }

    appendMessage(msgText);
    msgInput[0].value = "";
})

// 追加機能のEventを設定
title[0].addEventListener("click", () => {
  title[0].innerText = "BURN IT UP";
  msgChat[0].classList.add("msger-fire");
  main[0].classList.add("fire");
  setTimeout(() => {
    location.reload();
  }, "4000")
})

// HTMLベタうちから、createDiv関数を作成しリファクタリング
function appendMessage(text) {
  const parentDiv = createDiv(["msg", "right-msg"]);
  const imgDiv = createDiv(["msg-img"]);
  const bubble = createDiv(["msg-bubble"]);
  const infoDiv = createDiv(["msg-info"]);
  const timeDiv = createDiv(["msg-info-time"], formatDate(new Date()));
  const textDiv = createDiv(["msg-text"], text);
  
  const infoBlock = infoDiv.appendChild(timeDiv);
  bubble.appendChild(infoBlock);
  bubble.appendChild(textDiv);
  parentDiv.appendChild(imgDiv);
  parentDiv.appendChild(bubble);
  
  msgChat[0].appendChild(parentDiv);
  msgChat[0].scrollTop += 500;
}

function formatDate(date) {
  const hour = "0" + date.getHours();
  const min = "0" + date.getMinutes();
  
  return `${hour.slice(-2)}:${min.slice(-2)}`;
}

// 追加した関数
function createDiv(classArr, inner) {
  const newDiv = document.createElement("div");
  if(classArr !== undefined) {
    newDiv.classList.add(...classArr);
  }
  if(inner !== undefined) {
    newDiv.innerText = inner;
  }
  return newDiv;
}

まとめ

CSS苦手の民が、先人のコードを元にコーディングする時のポイントは、

  1. テーマカラーを決める
  2. テーマに沿って細かなCSSを調整する
  3. 自分に必要ないコードは削除する
    の3点です。

色や文字のフォント、線の太さを変えるだけでも印象が変わるので、基礎的なCSSを押さえておけばバッチリです。
もちろん自分でゼロイチでStyle当てられる方がいい!とは思う!けれど、作ってなんぼ精神で開発をしている人は、巨人の肩に乗りまくりましょう。どんなにいい機能があっても、見た目がダサければ目に留まらない。
CSS職人、愛してる。Codepen、ありがとう。精進します。

引用資料

おすすめ配色サイト

Discussion