<![CDATA[Liberation Notes]]>https://cmwang.net/https://cmwang.net/favicon.pngLiberation Noteshttps://cmwang.net/Ghost 5.78Fri, 12 Apr 2024 09:39:39 GMT60<![CDATA[Tell Me It's Not A Dream]]>https://cmwang.net/blog/2024/03/tell-me-its-not-a-dream/6604bd69191eeb37447055fcThu, 28 Mar 2024 00:56:43 GMT
最近很喜歡的歌曲與一句話 - "逆境中善待自己,順境中善待他人"
Tell Me It's Not A Dream

You are the light to my darkness
I just realized it
Your hand just fits in mine
So, hold it till the world ends
When you tell me your dreams
I don't need a reason
Just want to live in this moment
I'll never not breathe with you
🎵🎵

]]>
<![CDATA[Restaurant Waitlist Numbering System Design]]>https://cmwang.net/blog/2024/03/restaurant-waitlist-numbering-system-design/6604b6b0191eeb37447055cfMon, 18 Mar 2024 00:28:00 GMT

Recently, I encountered a fascinating job opportunity that tasked me with designing a waitlist numbering system for restaurants. I spent several days delving into this challenge, hypothesizing the problem and its potential solutions, and embarked on a detailed breakdown of the task. This involved considering various aspects such as the customer's experience of joining the waitlist, the technological infrastructure needed to support such a system, and how it could improve overall service efficiency and reduce waiting times. Moreover, I explored how the system could be scaled to fit restaurants of varying sizes and handle diverse customer flows. This endeavor turned out to be a highly enriching experience, granting me invaluable insights into the intersection of technology and customer service within the restaurant industry. It was a journey filled with learning and exploration that I felt was important to document.

Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.
A new tool that blends your everyday work apps into one. It’s the all-in-one workspace for you and your team
Restaurant Waitlist Numbering System Design

👆👆👆 Detailed Design

]]>
<![CDATA[🖥️ The Only CSS Layout Guide You'll Ever Need | EdRoh]]>https://cmwang.net/blog/2024/02/the-only-css-layout-guide-youll-ever-need/65be87b0138b1d75444ecf3dSat, 03 Feb 2024 19:19:08 GMT
🖥️ The Only CSS Layout Guide You'll Ever Need | EdRoh

Source: https://www.youtube.com/watch?v=i1FeOOhNnwU


Box

  • 拿到設計稿的第一件事情就是用 box 將一切視覺化。
  • CSS Box Model 預設使用 content-box ,此時只包含 content。如果你改用 border-box 則包含 border, padding, content。
  • 將版面切成 box 的順序是由上而下,由左而右 (由頂部開始橫向佈局)。因為 div 預設是佔滿一整 row (block element)。
  • 所有的 box 都有父子關係,理解這個關係有助於使用 flexbox 與 grid 系統。
  • 不要再使用 float 去定位版面了,預設先考慮 flexbox。
  • 有些人會使用絕對定位去排版,這樣就達不到 RWD 設計。

Flexbox

  • Parent attributes

    .parent {
      display: 'flex';
      flex-direction: 'row' | 'row-reverse' | ... (more);
      flex-wrap: 'nowrap' | 'wrap' | 'wrap-reverse';
      flex-flow: [flex-direction and flex-wrap values];
      justify-content: 'flex-start' | 'flex-end' | ... (more);
      align-items: 'stretch' | 'flex-start' | ... (more);
      align-content: 'stretch' | 'flex-start' | ... (more);
    }
    
  • Parent attributes 真正需要關注的只有:

    .parent {
      display: 'flex';
      justify-content: 'center' | 'space-between';
      align-content: 'center' | 'space-between';
    }
    
  • Child attributes

    • flex-grow
    • flex-basis
  • Flex Cheatsheet

]]>
<![CDATA[📚 Pinia State Management]]>https://cmwang.net/blog/2024/02/pinia-state-management/65bb9aa44c147810992a1b45Thu, 01 Feb 2024 13:27:08 GMTInitialize Pinia for your app
// /src/main.js

import "./assets/main.css";

import { createApp } from "vue";
import { createPinia } from "pinia"; // here 👈

import App from "./App.vue";

const app = createApp(App);

app.use(createPinia()); // here 👈
app.mount("#app");

Use the store

<template>
  <div class="counter-container">
    <!-- state (data) -->
    <h2>{{ storeCounter.count }}</h2>

    <!-- actions (methods)-->
    <button @click="storeCounter.increaseCount">+</button>
    <button @click="storeCounter.decreaseCount">-</button>
  </div>

  <!-- getters (computed) -->
  <div>The counter is {{ storeCounter.oddOrEven }}</div>

  <!-- two-way data binding-->
  <input v-model="storeCounter.count" type="number" />
</template>
<script setup>
  import {useCounterStore} from '@/stores/counter'; const storeCounter =
  useCounterStore();
</script>

Define the store (Composition API)

  • composition api store
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", () => {
  // State
  const count = ref(0);

  // Getters
  const doubleCount = computed(() => count.value * 2);
  const oddOrEven = computed(() => (count.value % 2 === 0 ? "even" : "odd"));

  // Actions
  function increaseCount() {
    count.value++;
  }

  function decreaseCount() {
    count.value--;
  }

  // Expose the state, getters, and actions
  return {
    count,
    doubleCount,
    oddOrEven,
    increaseCount,
    decreaseCount,
  };
});

Define the store (Options API)

  • options api store
import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", {
  // State
  state: () => ({
    count: 0,
  }),

  // Getters
  getters: {
    oddOrEven: (state) => (state.count % 2 === 0 ? "even" : "odd"),
  },

  // Methods (Actions)
  actions: {
    increaseCount() {
      this.count++;
    },
    decreaseCount() {
      this.count--;
    },
  },
});
]]>
<![CDATA[🎧 分手一百天 (break up 100 days) - AI (Lee Ji Eun)]]>https://cmwang.net/blog/2023/12/break-up-100-days/65bb9c804c147810992a1b60Sun, 31 Dec 2023 13:34:00 GMT
🎧 分手一百天 (break up 100 days) - AI (Lee Ji Eun)

詞:JC 陳詠桐 曲:JC 陳詠桐 編曲:褚鎮東

仍期待我可等到某天
重提舊愛不需眼淺
情人若要當好友能極友善
或悟到分手哪有伏線
現在愛戀都說變就變
而夜深單曲寄意能免則免

然而舊記憶彷似碎片
緩緩地刺於心裡邊
仍然未看得開和誰或者只可擦肩
復合每天想夠數十遍
為著更加匹配我願改變
無奈都清楚勉強亦會生厭

才與他分開一百天
會悲傷的確仍難免
畢竟真心愛過 內心注定痛點
我知往事如煙
我知已難重演
我怎會祈求街角碰面 假使那天
難道我的手他會牽

和誰錯愛亦是磨練
有些傷口確實難免
我畢竟擁有過 若失去是痛點
也許有幸來到一天
終於想起已能夠用笑容紀念
只怕或某次再想到這張臉
如掌心那根刺

難忘和舊愛太開心
難忘還是我太不甘
為何投入得過份最後只得我勇敢
隨年月抺去我天真
很清楚深愛沒法再這麼深
很怕若又愛錯 我不會再翻身

唯有講分開一百天
有些傷口確實難免
我畢竟擁有過 若失去是痛點
也許有幸來到一天
講得岀口對誰已無那份掛念
只怕或某次轉身再次相見
仍勾起這根刺

]]>
<![CDATA[📚 SCSS Crash Course]]>https://cmwang.net/blog/2023/12/scss-crash-course/65bb9f164c147810992a1b86Sun, 24 Dec 2023 16:00:00 GMT

SCSS 是一種用於簡化和增強 CSS 的語言,它具有變數、巢狀規則、混入、函數等功能,使得 CSS 更易於維護和擴展。

1. 安裝 Sass

首先,確保你的開發環境中已經安裝了 Sass。你可以使用 npm(Node.js 包管理器)來安裝 Sass:

npm install -g sass

2. 創建 SCSS 文件

在你的專案中,創建一個新的 .scss 文件,例如 styles.scss

3. 基本語法

變數 (Variable) 🔥

$primary-color: #3498db;
$font-size: 16px;

body {
  color: $primary-color;
  font-size: $font-size;
}

巢狀規則 (Nested) 🔥

nav {
  background: $primary-color;

  ul {
    list-style: none;
    padding: 0;

    li {
      display: inline-block;
      margin-right: 10px;
    }
  }
}

對應的 CSS

nav {
  background: $primary-color;
}

nav ul {
  list-style: none;
  padding: 0;
}

nav ul li {
  display: inline-block;
  margin-right: 10px;
}

父選擇器或巢狀選擇器 (Parent Selector) 🔥

在 SCSS 中,& 符號被稱為“父選擇器”(Parent Selector)或“嵌套選擇器”(Nested Selector)。它在 SCSS 中的主要作用是引用父選擇器的上下文,使得在嵌套的情況下能夠更靈活地構建和生成 CSS。

以下是一些常見用法:

  1. 嵌套選擇器:

    nav {
      background: #333;
    
      a {
        color: #fff;
        &:hover {
          text-decoration: underline;
        }
      }
    }
    
    • 對應的 CSS:
    nav {
      background: #333;
    }
    
    nav a {
      color: #fff;
    }
    
    nav a:hover {
      text-decoration: underline;
    }
    

    在這裡,& 用於引用其上下文中的父選擇器 nav

  2. 擴展選擇器:

    .button {
      background: blue;
      &.active {
        background: red;
      }
    }
    
    • 對應的 CSS:
    .button {
      background: blue;
    }
    
    .button.active {
      background: red;
    }
    

    在這裡,& 被用於嵌套地構建 .button.active

混入 (Mixin) 🔥

@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
  -moz-border-radius: $radius;
  border-radius: $radius;
}

.box {
  @include border-radius(10px);
}

導入 (Import) 💡

// _variables.scss
$primary-color: #3498db;

// styles.scss
@import "variables";

body {
  color: $primary-color;
}

擴展 (Extend) 💡

擴展是一種 SCSS 功能,允許你使用一個選擇器的樣式來擴展另一個選擇器的樣式,類似於 CSS 中的類。這可以減少代碼的重複並提高可維護性。

  • SCSS 範例

    %button-style {
      display: inline-block;
      padding: 10px 20px;
      font-size: 16px;
    }
    
    .btn-primary {
      @extend %button-style;
      background-color: #3498db;
      color: #fff;
    }
    
    .btn-secondary {
      @extend %button-style;
      background-color: #e74c3c;
      color: #fff;
    }
    

    在這個例子中,%button-style 是一個 placeholder,它包含了通用的按鈕樣式。然後,btn-primarybtn-secondary 透過 @extend 將這些通用樣式擴展到具體的按鈕類別中。

  • 對應的 CSS

    .btn-primary, .btn-secondary {
      display: inline-block;
      padding: 10px 20px;
      font-size: 16px;
    }
    
    .btn-primary {
      background-color: #3498db;
      color: #fff;
    }
    
    .btn-secondary {
      background-color: #e74c3c;
      color: #fff;
    }
    

函數 (Function)

SCSS 允許你定義和使用函數,這樣你就可以更靈活地處理數據和生成樣式。

  • SCSS 範例

    @function calculate-width($width, $padding) {
      @return $width + 2 * $padding;
    }
    
    .container {
      width: calculate-width(200px, 10px);
      padding: 10px;
    }
    

    在這個例子中,calculate-width 函數接受兩個參數:$width$padding,然後返回計算後的寬度。這個函數被用於設置 .container 元素的寬度。

4. 編譯 SCSS 到 CSS

在終端機中執行以下命令,將你的 SCSS 文件編譯成 CSS:

sass input.scss output.css

或者,如果你想要在每次保存文件時自動編譯,可以使用以下命令:

sass --watch input.scss:output.css

5. Sass 與 SCSS 語法差異

Sass(Syntactically Awesome Stylesheets)和 SCSS(Sassy CSS)都是 CSS 預處理器,它們提供了一些額外的功能和語法來更有效地編寫和管理樣式表。以下是 Sass 和 SCSS 的主要差異:

  1. 語法差異:
  • Sass: 使用縮進來表示區塊和層次結構,並且不使用分號和大括號。例如:

    body
      font: 14px/1.4 "Helvetica Neue", sans-serif
      color: #333
    
    .container
      width: 100%
      margin: 0 auto
    
    
  • SCSS: 使用大括號表示區塊和分號來結束每個聲明,更接近傳統的 CSS 語法。例如:

    body {
      font: 14px/1.4 "Helvetica Neue", sans-serif;
      color: #333;
    }
    
    .container {
      width: 100%;
      margin: 0 auto;
    }
    
  1. 文件擴展名:
  • Sass: Sass 文件使用 .sass 作為擴展名。
  • SCSS: SCSS 文件使用 .scss 作為擴展名。
]]>
<![CDATA[🐘 PDO Crash Course]]>https://cmwang.net/blog/2023/12/pdo-crash-course/65bb9e5a4c147810992a1b72Sat, 16 Dec 2023 16:00:00 GMT 🐘 PDO Crash Course

PDO (PHP Data Objects) is a database access layer providing a uniform method of access to multiple databases. It is a secure and efficient way to interact with databases in PHP.

1. Connecting to a Database

<?php
$host = 'localhost';
$dbname = 'your_database_name';
$username = 'your_username';
$password = 'your_password';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "Connected successfully";
} catch (PDOException $e) {
    echo "Connection failed: " . $e->getMessage();
}
?>

The line $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); sets the error handling mode for PDO. Specifically, it sets PDO to throw exceptions when errors occur.

  • PDO::ATTR_ERRMODE: This is an attribute that controls the error reporting mode.
  • PDO::ERRMODE_EXCEPTION: This mode causes PDO to throw exceptions when errors occur, making it easier to handle errors in your code.

So, if there's an error in a PDO operation, it will throw an exception, and you can catch that exception to handle errors more gracefully.

2. Executing Queries

  • SELECT Statement

    $stmt = $pdo->prepare('SELECT * FROM your_table_name');
    $stmt->execute();
    
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    foreach ($result as $row) {
        // Process each row as needed
        echo $row['column1'] . "\t" . $row['column2'] . "\n";
    }
    
    • fetchAll: This method is used to fetch all rows from the result set returned by a prepared statement. It retrieves all the rows into an array.
    • PDO::FETCH_ASSOC: This is a fetch style constant provided by PDO that specifies the format in which the rows should be fetched. In this case, FETCH_ASSOC indicates that the rows should be fetched as an associative array where the column names are used as keys.
  • INSERT Statement:

    $data = ['value1', 'value2'];
    $stmt = $pdo->prepare('INSERT INTO your_table_name (column1, column2) VALUES (?, ?)');
    $stmt->execute($data);
    echo "Data inserted successfully";
    
  • UPDATE Statement:

    $newValue = 'new_value';
    $id = 1;
    $stmt = $pdo->prepare('UPDATE your_table_name SET column1 = ? WHERE id = ?');
    $stmt->execute([$newValue, $id]);
    echo "Data updated successfully";
    
    
  • DELETE Statement:

    $id = 1;
    $stmt = $pdo->prepare('DELETE FROM your_table_name WHERE id = ?');
    $stmt->execute([$id]);
    echo "Data deleted successfully";
    

3. Prepared Statements and Parameter Binding:

Prepared statements help prevent SQL injection by separating SQL code from user input.

$username = 'user';
$password = 'pass';

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();

$result = $stmt->fetch(PDO::FETCH_ASSOC);

In this example, placeholders (:username and :password) are used in the query, and then values are bound to these placeholders using bindParam. This helps prevent SQL injection and allows for better reuse of the prepared statement.

4. Error Handling

Always handle errors to ensure a robust application.

]]>
<![CDATA[🖥️ Learn CSS Grid the easy way | Kevin Powell]]>https://cmwang.net/blog/2023/11/learn-css-grid-the-easy-way/65bba2084c147810992a1ba8Thu, 30 Nov 2023 13:55:00 GMT
🖥️ Learn CSS Grid the easy way | Kevin Powell

source: https://www.youtube.com/watch?v=rg7Fvvl3taU

⚙️ 方法1

從攏統開始,除非需要特別指定,才處理特別之處,簡化設計。

  • grid-template-columns

    .testimonial-grid {
      display: grid;
      gap: 1.5rem;
      grid-template-columns: repeat(3, 1fr);
    }
    
  • grid-template-rows 盡量不用, 讓它自己長 (隱式網格,Implicit Grid Rows),簡化設計

  • gap

    grid-row-gap: 20px;
    grid-colume-gap: 10px;
    
    /* or */
    gap: 20px 10px; /* Different row and column gaps */
    
    /* or */
    gap: 1.5rem;
    
  • span (在 grid item 上)

    .grid-col-span-2 {
       grid-column: span 2;
    }
    
    <article class="testimonial grid-col-span-2 ...">
    
  • 處理特別的卡片,個別指定開始跟結束

    .testimonial:last-child {
      grid-column-start: 4;
      grid-column-end: 5;
      grid-row-start: 1;
      grid-row-end: 3; /* or span 2 */
    }
    
    /* or 縮寫 */
    .testimonial:last-child {
      grid-column: 4 / 5;
      grid-row: 1 / 3; /* or 1 / span 2 */
    }
    
  • media query (mobile first)

    • @media (min-width: 40em) {} 表示當螢幕寬度大於或等於 40em 時套用樣式。這是使用 min-width 的情況。
    • 在 mobile-first 設計中,通常會使用 min-width,因為一開始的樣式是針對較小的螢幕(例如手機)設計的,然後使用媒體查詢逐漸增加樣式以適應較大的螢幕。因此,一開始的樣式將不帶有媒體查詢,而後續的樣式將使用 min-width 來確保它們只在螢幕寬度超過特定值時套用。
  • 💪💪💪 Final

    @media (min-width: 40em) {
      .grid-col-span-2 {
         grid-column: span 2;
      }
    
      .testimonial-grid {
        display: grid;
        gap: 1.5rem;
        grid-template-columns: repeat(4, 1fr);
      }
      
      .testimonial:last-child {
        grid-column-start: 4;
        grid-row: 1 / span 2;
      }
    }
    
  • 🔥 使用 Tailwind CSS 達到同樣效果

    <div class="grid-container grid grid-cols-1 gap-4 md:grid-cols-4">
      <div class="itm border-2 md:col-span-2">1</div>
      <div class="itm border-2">2</div>
      <div class="ite border-2">3</div>
      <div class="ite border-2 md:col-span-2">4</div>
      <div class="ite border-2 md:col-start-4 md:row-span-2 md:row-start-1">5</div>
    </div>
    

⚙️ 方法2

  • grid-template-areas

    • grid-template-areas 屬性用於定義 CSS Grid 的區域佈局。
    • 透過指定區域名稱,可以輕鬆地組態子元素的位置。
    • .testimonial-grid 中,使用了五個區域名稱 one, two, three, four, five 來定義區域。
    • 注意最後的分號🔥。
  • nth-child() 這部分如果不設定,會錯位

    • nth-child() 是 CSS 選擇器中的一種,用於選擇父元素的特定子元素。
    • 在這裡,.testimonial:nth-child(n) 被用來選擇 .testimonial 元素中的第 n 個子元素,並且透過 grid-area 屬性指定它們在 grid 中的區域。
    • 如果移除了 .testimonial:nth-child(n) 選擇器中的 grid-area 屬性,將會影響到 grid 的佈局。在這個特定的情境中,.testimonial-grid 使用了 grid-template-areas 來定義區域佈局,而 .testimonial:nth-child(n) 選擇器被用來將特定的 .testimonial 元素放置到相應的區域。
    • 如果省略了 grid-area.testimonial 元素將不會被對應到指定的區域,而是預設將它們按照正常的流動放置在 grid 中。這可能會導致 grid 的佈局混亂,因為沒有確定每個 testimonial 應該放置在哪個區域。
    • 簡而言之,.testimonial 元素的位置不再受到 grid-template-areas 的影響,它們將按照正常文檔流的方式排列。這可能會使得原本為每個 testimonial 定義的區域佈局失效,並可能造成不符合預期的外觀。
  • grid-auto-columns 讓 column 等寬,不然就會自然流動分配

    • 如果移除了 .testimonial-grid 中的 grid-auto-columns 屬性,則將影響到自動生成欄的寬度。在這裡,grid-auto-columns: 1fr; 的設置表示自動生成的欄寬度均為 1fr。
    • 如果省略了 grid-auto-columns,則自動生成的欄將使用預設的欄寬度。這可能會影響到該 grid 的外觀,特別是當沒有明確定義欄寬度時,欄的寬度可能會被內容的寬度所影響。
    • 簡而言之,grid-auto-columns 的存在有助於明確指定自動生成的欄的寬度,而省略它將使用默認值。具體影響取決於其他樣式規則和內容的特性,但在這個例子中,可能會導致 grid 的欄寬度不如預期。
  • 💪💪💪 Final

    .testimonial-grid {
      display: grid;
      gap: 1.5rem;
      grid-auto-columns: 1fr; /* 🔥 */
      grid-template-areas:
        'one'
        'two'
        'three'
        'four'
        'five'; /* don't forget */
    }
    
    .testimonial:nth-child(1) {
      grid-area: one;
    }
    .testimonial:nth-child(2) {
      grid-area: two;
    }
    .testimonial:nth-child(3) {
      grid-area: three;
    }
    .testimonial:nth-child(4) {
      grid-area: four;
    }
    .testimonial:nth-child(5) {
      grid-area: five;
    }
    
    @media (min-width: 50em) {
      .testimonial-grid {
        grid-template-areas:
          'one one two five'
          'three four four five';
      }
    }
    

CodePen

]]>
<![CDATA[🖥️ DHH: Microservices vs. Monolith | Honeypot]]>https://cmwang.net/blog/2023/11/dhh-microservices-vs-monolith/65badd56514868c0d44d1b20Sat, 18 Nov 2023 23:59:00 GMT

組織結構考慮

🖥️ DHH: Microservices vs. Monolith | Honeypot

DHH 強調選擇微服務或單體架構更多地涉及組織結構而非程式碼組織。微服務適合大團隊,而對於 10 至 100 名開發人員的小團隊,單體架構更簡單、更高效。

單體架構的簡易性

DHH 主張單體架構的簡易性,表示對於較小的團隊,避免在微服務中替換方法呼叫為網路呼叫的複雜性可以簡化開發。單體架構消除了管理基本功能的網路連線的需要,減少了複雜性並簡化了偵錯過程。

模式的適用性

DHH 警告不要將為大型組織(如 Netflix)設計的模式應用於較小的團隊,因為這樣做通常會導致不良結果。他認為在沒有相應組織上下文的情況下採用微服務可能會帶來不必要的複雜性。

宏偉的單體架構 (The Majestic Monolith)

DHH 表達了對單體架構的強烈偏好,創造了The Majestic Monolith這一術語。他主張在儘可能長的時間內保持儘可能簡單,並表示單體架構對於較小的開發團隊特別有益。

]]>
<![CDATA[🎧 迷途 (Astray) - AI (Lee Ji Eun)]]>https://cmwang.net/blog/2023/11/ai-iu-astray/65ba5e4dd5373f88eb1a0a5dTue, 14 Nov 2023 07:51:00 GMT🎧 迷途 (Astray) - AI (Lee Ji Eun)

詞:林阿與 曲:鄭冰冰

黑夜撥動時針
喧囂逐漸代替無聲
我們演著相遇劇本
鑲嵌夜的彩虹
還有穿過沙漠的風
都曾經是我們的見證

誰不是茫茫中迷途的人
找尋 億萬分之一的可能
困在這 名為命運的城
卻依舊追逐著星辰
別擔心 我愛著的迷途的人
執杯酒 溫暖孤獨靈魂
讓我擁抱 你的裂痕
你如星燦爛 閃爍在落寞時分

黑夜撥動時針
喧囂逐漸代替無聲
我們演著相遇劇本
鑲嵌夜的彩虹
還有穿過沙漠的風
都曾經是我們的見證

誰不是茫茫中迷途的人
找尋 億萬分之一的可能
困在這 名為命運的城
卻依舊追逐著星辰
別擔心 我愛著的迷途的人
執杯酒 溫暖孤獨靈魂
讓我擁抱 你的裂痕
你如星燦爛 閃爍在落寞時分

誰不是茫茫中迷途的人
找尋 億萬分之一的可能
困在這 名為命運的城
卻依舊追逐著星辰
別擔心 我愛著的迷途的人
執杯酒 溫暖孤獨靈魂
讓我擁抱 你的裂痕
你如星燦爛 閃爍在落寞時分

]]>
<![CDATA[📚 CSS Grid]]>https://cmwang.net/blog/2023/11/css-grid/65bae107514868c0d44d1b3cMon, 13 Nov 2023 16:10:00 GMTTerminology
  • 網格項目 (grid item): 網格布局中的元素,可以是任何 HTML 元素。
  • 網格單元格 (grid cell): 網格中的一個矩形區域,由行和列組成。
  • 網格軌道 (grid track): 網格中一行或一列的區域。
📚 CSS Grid

Grid Sizing

📚 CSS Grid

fr 是指 "fractional unit",它是一種相對單位,用於指定網格容器(grid container)中的列(columns)或行(rows)的大小

/* auto */
.container {
  display: grid;
  grid-template-rows: 100px auto; /* 高的 auto 只會 fit content */
  grid-template-columns: 200px auto; /* 寬的 auto 會填滿 100%寬 🔥 */
}

/* minmax */
.container {
  display: grid;
  grid-template-rows: 200px 400px;
  grid-template-columns: 200px minmax(400px, 800px);
}

/* repeat */
.container {
  display: grid;
  grid-template-columns: repeat(8, 1fr); /* 8 columns, each 100px wide */
  grid-template-rows: repeat(8, 1fr); /* 8 rows, each 100px tall */
}

/* grid auto rows 🔥 */
.container {
  display: grid;
  grid-template-columns: 200px 200px;
  grid-template-rows: 200px 200px;
  grid-auto-rows: 300px; /* 超出的格子,未來設為高度300px 🔥 */
}

Position Grid Items

1. 使用 grid-columngrid-row 屬性

這種方式通過指定網格項目的起始和終止線的位置來定位它。例如:

.grid-item {
  grid-column: 2 / 4; /* 從第 2 col 到第 4 col */
  grid-row: 1 / 3; /* 從第 1 row 到第 3 row */
  grid-row: 1 / span 2;
  grid-row: 1 / -1;
  /* ... 以下參考就好,不要用 ❌ */
  grid-column: span 2;
  grid-column-start: 2;
  grid-column-end: -1;
  grid-area: 1 / 3 / 2 / 4; /* row-start, column-start, row-end, column-end  */
}

2. 使用命名的網格線(Named Grid Lines)

你可以在 grid-template-columnsgrid-template-rows 屬性中使用名稱來定義網格線,然後在 grid-columngrid-row 屬性中使用這些名稱。例如:

.grid-container {
  display: grid;
  grid-template-columns: [col1] 1fr [col2] 1fr [col3 test] 1fr;
  grid-template-rows: [row1] 100px [row2] 100px [row3] 100px;
}

.grid-item {
  grid-column: col1 / col3 | test; /* 從 col1 到 col3 的列 */
  grid-row: row1 / row3; /* 從 row1 到 row3 的行 */
}

3. 使用命名的網格區域(Named Grid Areas):

你可以在網格容器中使用 grid-template-areas 屬性為不同的區域命名,然後在網格項目中使用 grid-area 屬性引用這些名稱。例如:

.grid-container {
  display: grid;
  grid-template-areas:
    "header header ." /* 用點留白 🔥 */
    "main main sidebar"
    "footer footer footer";
}

.grid-item {
  grid-area: main; /* 使用 "main" 命名的區域 */
}

Implicit Grids

在 CSS Grid 中,grid-auto-rows|columnsgrid-auto-flow 是用於控制網格自動生成的兩個重要屬性。

1. grid-auto-rowsgrid-auto-columns

grid-auto-rows 屬性用於指定網格容器中那些由自動生成的列的高度。當你的網格項目超出了你在 grid-template-rows 中明確定義的列數時,這些額外的列會由 grid-auto-rows 屬性來控制。例如:

.grid-container {
  display: grid;
  grid-template-rows: 100px 100px; /* 兩個明確定義的行 */
  grid-auto-rows: 50px; /* 自動生成的行的高度 */
}

在這個例子中,如果你有超過兩個網格項目,額外的行高度將為 50px。

2. grid-auto-flow

grid-auto-flow 屬性用於指定在添加新的網格項目時,它們應該如何放置到網格容器中。這個屬性有四個值:

  • row(預設值):新的項目將按照行添加。
  • column:新的項目將按照列添加。
  • dense:網格容器將嘗試將項目填充到所有的空隙,而不僅僅是按照順序添加。
  • dense column:組合了 densecolumn,新的項目將按照列添加,同時容器會嘗試填充所有的空隙。

例如:

.grid-container {
  display: grid;
  grid-auto-flow: column; /* 新的項目將按照直行添加 */
}

CSS Grid 中的大小選項

在 CSS Grid 中,min-contentmax-contentminmax()函數被用來以一種靈活且具有響應性的方式來定義網格軌道(行或列)的大小。

  1. min-content:這個關鍵字將軌道的大小設置為其內容的最小內在大小。換句話說,它使軌道的大小盡可能小,同時仍然容納其內容。

    grid-template-columns: min-content 1fr min-content;
    

    在這個例子中,第一行和第三行將根據它們包含的最小內容寬度來設置大小,而第二行將占據剩餘的可用空間。

  2. max-content:這個關鍵字將軌道的大小設置為其內容的最大內在大小。它使軌道的大小足以容納其內容,而不會溢出。

    grid-template-columns: max-content 1fr max-content;
    

    類似於min-content,這個例子將基於它們包含的最大內容寬度來設置第一列和第三列的大小,而第二行將占據剩餘的可用空間。

  3. minmax(min, max):這個函數允許你為軌道的大小指定一個範圍。它接受兩個參數,即最小大小最大大小。瀏覽器將根據網格容器中的可用空間在這些值之間分配空間。

  • minmax() 可以用以下任何值:

    • 長度
    • %
    • fr
    • max-content
    • min-content
    • auto
grid-template-rows: minmax(min-content, 200px) 1fr minmax(100px, max-content);

在這個例子中,第一列的大小將基於最小內容寬度,但不會小於內容的內在大小。第二列占據剩餘的空間,而第三列的大小將基於最大內容寬度,但不會大於 200 像素。

Grid auto-fillauto-fit

在 CSS Grid 中,auto-fillauto-fit是與grid-template-columnsgrid-template-rows屬性一起使用的兩個值。

  1. Auto-fill

    • auto-fill關鍵字用於重複可用的網格軌道(列或行)盡可能多次,以填充可用空間。
    • 它創建盡可能多的軌道,而不會溢出容器。

    例子:

    .container {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    }
    

    在此示例中,grid-template-columns屬性設置為repeat(auto-fill, minmax(100px, 1fr));。它創建盡可能多的行,最小大小為100px,最大大小為1fr(可用空間的一部分)。

  2. Auto-fit

    • auto-fit關鍵字與auto-fill類似,但它還會折疊任何空的軌道。如果項目未填滿所有可用的軌道,則空的軌道將被折疊(寬度為 0),網格僅占據必要的空間

    例子 (RWD Trick 🔥🔥🔥):

    .container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    }
    

    類似於前一個例子,這裡使用了auto-fit。它創建盡可能多的行,最小大小為100px,最大大小為1fr,但任何空的軌道都將折疊,網格容器僅占據必要的寬度。


以下是一些使用 auto-fillauto-fit 的示例:

  • 創建一個響應式網格,該網格將根據屏幕的寬度自動調整 col 數:
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 1fr);
}
  • 創建具有固定 col 數的網格,無論屏幕的寬度是多少:
.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
  • 創建具有 col 的網格,這些 col 始終具有相同的寬度,無論網格項的數量是多少:
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, 100px);
}
]]>
<![CDATA[📚 CSS Unit]]>https://cmwang.net/blog/2023/11/css-units/65bb98814c147810992a1b1fSun, 12 Nov 2023 16:00:00 GMT% 百分比
  • 如果用於指定字體大小,則相對於其父元素的字體大小進行測量。
  • 如果用於指定長度,則相對於其父元素的寬度進行測量。
/* 父元素 */
.parent {
  font-size: 16px;
  width: 300px;
}

/* 子元素 */
.child {
  font-size: 100%; /* 字體大小相對於父元素的字體大小, 16px */
  width: 50%; /* 寬度相對於父元素的寬度, 150px */
  padding: 1em; /* 內部填充相對於當前的字體大小 16px */
}

em (相對 EM)

  • 如果用於指定字體大小,則相對於其父元素的字體大小進行測量。
  • 如果用於指定長度,則相對於當前的字體大小進行測量。 🔥
📚 CSS Unit

用 EM 指定長度,需注意是用當前字體大小當基準。若當前沒指定,用繼承來的字體大小當基準。

/* 父元素 */
.parent {
  font-size: 16px;
  width: 300px;
}

/* 子元素 */
.child {
  font-size: 2em; /* 字體大小相對於父元素的字體大小 32px */
  width: 3em; /* 寬度相對於相對於[當前]的字體 32px x 3 = 96 px 🔥 */
}

rem (Root EM)

  • REM (Root EM) 是相對於文檔的 Root element (html 元素) 的字體大小進行測量。
  • REM 提供了一種統一的基準,使得在整個文檔中可以輕鬆地維護一致的尺寸比例。
/* 設定根元素字體大小 */
html {
  font-size: 16px;
}

/* 父元素 */
.parent {
  font-size: 1rem; /* 字體大小相對於根元素 16px */
  width: 300px;
}

/* 子元素 */
.child {
  font-size: 2rem; /* 字體大小相對於根元素 32px */
  width: 3rem; /* 寬度相對於根元素 48px */
}

vwvh (Viewport Width & Height)

  • vw 表示相對於視窗寬度的百分比。
  • vh 表示相對於視窗高度的百分比。
/* 父元素 */
.parent {
  font-size: 16px;
  width: 50vw; /* 寬度相對於視窗寬度的50% */
}

/* 子元素 */
.child {
  font-size: 2em; /* 字體大小相對於父元素的字體大小 32px */
  width: 50vh; /* 寬度相對於視窗高度的50% */
}
]]>
<![CDATA[📚 Understanding CSS Opacity, Visibility, and Display]]>https://cmwang.net/blog/2023/11/css-opacity-visibility-display/65bb999d4c147810992a1b31Sun, 12 Nov 2023 16:00:00 GMT 📚 Understanding CSS Opacity, Visibility, and Display

key differences between opacity: 0, visibility: hidden, and display: none:

Property Visibility Layout Interaction
opacity: 0 Invisible Yes Yes
visibility: hidden Invisible Yes No
display: none Hidden No No
]]>
<![CDATA[📚 CSS Tricks]]>https://cmwang.net/blog/2023/11/css-tricks/65bb98004c147810992a1b0eSun, 12 Nov 2023 16:00:00 GMTCSS Reset
📚 CSS Tricks

Do not set the font property in the universal selector. Instead, set it in the body selector for inheritance and performance.

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: inherit; /* border-box */
}

html {
  font-size: 62.5%; /* 10px = 16px * 62.5% */
}

body {
  box-sizing: border-box; /* here */
  font-family: ....;
  font-weight: ...;
  line-height: ...;
  color: ...;
  padding: ...;
}

Element Center (簡易版)

  • The easiest way to center anything with the transform, top and left properties.
.text-box {
  position: absolute; /* relative to parent container */
  top: 50%;
  left: 50%;
  transfrom: translate(-50%, -50%);
}

Faded overlay on image

.header {
  height: 95vh;
  background-image: linear-gradient(
      to right bottom,
      rgba(126, 213, 111, 0.8),
      rgba(38, 181, 133, 0.8)
    ), url(img/hero.jpg); /* two layers */
  background-size: cover; /* 背景圖片會被縮放以完全覆蓋背景區,可能背景圖片部分看不見 */
  background-position: top; /* 縮放時,上半部不會被裁切 */
}

Fade in Animation

@keyframes moveInLeft {
  0% {
    opacity: 0;
    transform: translateX(-100px);
  }

  80% {
    transform: translateX(20px);
  }

  100% {
    opacity: 1;
    transform: translate(0); /* reset */
  }
}

.who-need-this-animation {
  /* animation */
  animation-name: moveInLeft;
  animation-duration: 1s;
  animation-timing-function: ease-out;
}

RWD Grid

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
]]>
<![CDATA[📚 CSS Critical Rendering Path (CRP)]]>https://cmwang.net/blog/2023/11/css-crp/65bb96f94c147810992a1af5Sat, 11 Nov 2023 16:00:00 GMT 📚 CSS Critical Rendering Path (CRP)

Behind the scenes when a web page is loaded and rendered:

  1. Load HTML

    • The browser starts by fetching and loading the HTML file.
  2. Parse HTML

    • The HTML file is parsed to create the Document Object Model (DOM). The DOM represents the structure of the document as a tree of objects, where each object corresponds to a part of the document (e.g., elements, attributes).
  3. Load CSS

    • If there are linked or inline stylesheets in the HTML, the browser fetches and loads them.
  4. Parse CSS

    • The loaded CSS files are parsed to create the CSS Object Model (CSSOM). This represents the styles and layout information defined in the CSS.
    • Resolve Conflicting CSS Declarations:
      • If there are conflicting CSS declarations (i.e., rules that apply to the same element and property), the browser uses a specific set of rules to determine which styles take precedence.
    • Process Final CSS Values:
      • The browser processes the final computed values for each CSS property, taking into account inheritance, specificity, and other rules.
  5. Render Tree

    • The DOM and CSSOM are combined to create the Render Tree. The Render Tree represents the visual hierarchy of the elements on the page that will be rendered. It includes only the elements that will actually be displayed.
  6. The Visual Formatting Model

    • The visual formatting model takes the render tree and calculates the layout of each element on the page. This includes determining the size and position of each element based on its CSS properties.
    • The visual formatting model also takes into account factors like the box model (margins, borders, padding), positioning, and floating elements.
  7. Render the Page

    • Finally, the browser renders the page by painting each pixel according to the specifications of the visual formatting model.

📚 CSS Critical Rendering Path (CRP)
Image source: Critical CSS in WordPress: What It Is and How to Optimize CSS Delivery

]]>