VStack
🔰 CSS ⟩ Layout ⟩ System ⟩ 🔸 code ┊問題
Every Layout ⟩ Stack /⭐️
SwiftUI ⟩ VStack
MDN ⟩
HTMLElement ⟩ dataset (: DOMStringMap) - get/set "data-xxx" attributes ⭐️
Element ⟩
CSS ⟩
@import - import styles from other style sheets.
Using data attributes ("data-xxx" attributes) ⭐️
attr() - use element's attributes in CSS ⭐️
用哪個好? <vstack-> 或 <i-vstack> ❓(這兩個都是合法的名字) 💾 replit ⟩ <vstack-> valid name?
version
// 0.0.5 + helpers
import {attr} from './helpers.mjs';
// VStack
export default class VStack extends HTMLElement {
// this.render()
render() {
const {spacing, alignment} = this;
const attrs = [spacing, alignment].filter(attr => !!attr); // remove empty attributes
// if no specific settings, use default values and return.
if (attrs.length === 0) return;
// style ID for this element
const styleID = `VStack-${attrs.join('_')}`;
// put vstack style ID in "data-xxx" attribute
this.dataset.style = styleID;
// if no such <style> with this ID, create it.
if (!document.getElementById(styleID)) {
// create <style>
let style = document.createElement('style');
style.id = styleID;
// concate css rules
const rules = [
// spacing between items
`${spacing ? `[data-style="${styleID}"] > * + :not(i-spacer) {margin-top: ${spacing};}` : ''}`,
// stack alignmentment
`${alignment ? `[data-style="${styleID}"] {align-items: ${alignment};}` : ''}`,
]
.filter(rule => rule !== '') // remove empty rules
.join('\n');
style.innerHTML = `${rules}`;
document.head.appendChild(style);
}
}
// -------------- getters/setters -------------------------
// this.spacing (= '30px')
get spacing() { return attr(this, 'spacing') }
set spacing(val) { return attr(this, 'spacing', val) }
// this.alignment (= 'flex-start' | 'center' | 'flex-end')
get alignment() { return attr(this, 'alignment') }
set alignment(val) { return attr(this, 'alignment', val) }
// -------------- lifecycle callbacks -------------------------
// ⭐ connected to document
connectedCallback() {
this.render();
}
// ⭐ observed attributes
static get observedAttributes() {
return ['spacing', 'alignment'];
}
// re-renders whenever one of attributes changes.
attributeChangedCallback() {
this.render();
}
}
// ⭐️ register <vstack->
customElements.get('vstack-') || customElements.define('vstack-', VStack);
/* 0.1.0 - align-items: center -> stretch */
/* VStack */
vstack- {
display: flex;
flex-direction: column;
align-items: stretch;
}
/* VStack 內非 spacer 的間隔 */
vstack- > * + :not(spacer-) {
margin-top: var(--spacing);
}
/*
如果只有唯一一個 VStack,就讓它的高度為 100%,
這樣裡面的 spacer 才能發生作用。
⭐️ 注意:
此設定一定要「母物件」有「明確設定」height 才有效❗️
母物件設定 min-height 沒有任何幫助喔❗️
*/
vstack-:only-child {
height: 100%;
}
replit ⟩ layout 0.1.0 - align-items: center ➜ stretch
code lab
/* ⭐️ HStack */
.hstack {
display: flex;
flex-direction: row;
}
/* ⭐️ VStack */
.vstack {
display: flex;
flex-direction: column;
}
/* ⭐️ Spacer */
.hstack > .spacer {
margin-left: auto;
width: 0;
border: none;
}
.vstack > .spacer {
margin-top: auto;
height: 0;
border: none;
}
寫一個 <spacer> 來代替 splitAfter❓(可行)
問題
<i-vstack align="right" class="container">
當在 custom element <i-vstack> 中輸入屬性 align="right",竟然會引發 browser 自動將它轉為:(🤔 align="..." 竟然對 custom element 也有效❓)
i-vstack[Attributes Style] {
text-align: right;
}
導致內部的所有子元素都繼承到此 text-align 性質:
HTML align attribute supports col, colgroup, tbody, td, tfoot, th, thead, tr elements. Usage of align attribute for any other HTML elements is deprecated. You must use CSS for those. 📗 w3resource ⟩ HTML align attribute
解決方案: 嘗試將 align="..." 改為 alignment="..." 看看。(結果 OK ✅)
解決方案:
// ⭐️ register new tag <i-vstack>
customElements.get('i-vstack') ||
customElements.define('i-vstack', VStack);
In order for a % value to work for height, the parent's height must be determined. 🗣 Why doesn't height: 100% working?
如果都是用百分比,則一路從 html ⟩ body ⟩ .... ⟩ 到自己的直屬母物件都要有明確設定 %,否則只要中間有一層斷掉也是沒用。
/*
當我們設定 height: 100% 時,此設定並不會真正發生作用,
除非它的母物件有「明確設定」height。
⭐️ 注意:設定母物件的 min-height 並沒有幫助❗️
*/
i-vstack:only-child {
height: 100%;
}
TutorialPublic ⟩ How to set the height of a div to 100% using CSS
MDN ⟩ CSS ⟩
Last updated