HTML / 屬性 === ###### tags: `frontend / HTML` ###### tags: `frontend`, `HTML` <br> [TOC] <br> ## entity name - [[HTML] Living Standard — Last Updated 15 September 2022](https://html.spec.whatwg.org/multipage/named-characters.html) - 背斜線:[\&bsol; represents reverse solidus (backward solidus)](https://stackoverflow.com/a/32329887/4359712) - Slash : / : \&#47; : \&sol; - Backslash : \ : \&#92; : \&bsol; <br> ## 全域屬性 - ### [HTML Global Attributes](https://www.w3schools.com/tags/ref_standardattributes.asp) - class - id - title <br> ## 比較 ### innerText vs. innerHTML vs. textContent - ### [What’s Best: innerText vs. innerHTML vs. textContent](https://betterprogramming.pub/903ebc43a3fc) - innerText: 頁面渲染後的純文字 (包含換行) - innerHTML: 頁面渲染前的原始碼 - textContent: 頁面渲染前的原始碼,但要去掉 tag,且包含 script, css 的內容 - ### 測試範例 ```html= <div class="box"> <h2> 星期六</h2> <script>const x = 0;</script> <p> 待在家寫 code </p> </div> ``` ![](https://i.imgur.com/q5MxjW9.png) <br> ### pre, xmp - [Html之pre、xmp標籤_感覺沒什麼用_例項](https://www.796t.com/content/1549137637.html) <br> <hr> <br> ## label & inputs[name=radio|checkbox] ### label 與 input 所觸發的事件順序為何 - ### 結論: - 一般行為 ``` <label onclick="labelClicked()"> Click me: <input type="radio" name="option" onclick="inputClicked()"> </label> ``` - 點擊 "Click me" 文字,觸發: - Label clicked (label 會觸發 input -> Input clicked) - Input clicked - Label clicked (input 會向上傳遞事件 -> label clicked) - 點擊 "radio" 按鈕,觸發: - Input clicked - Label clicked (input 會向上傳遞事件 -> label clicked) - 使用 event.stopPropagation ``` <script> function inputClicked() { console.log('Input clicked'); event.stopPropagation(); } function labelClicked() { console.log('Label clicked'); event.stopPropagation(); } </script> <body> <label onclick="labelClicked()"> Click me: <input type="radio" name="option" onclick="inputClicked()"> </label> </body> ``` - 點擊 **"Click me"** 文字,觸發: - Label clicked (label 會觸發 input -> Input clicked) - Input clicked - ~~Label clicked (input 會向上傳遞事件 -> label clicked)~~ (因 `event.stopPropagation()`) - 點擊 **"radio"** 按鈕,觸發: - Input clicked - ~~Label clicked (input 會向上傳遞事件 -> label clicked)~~ (因 `event.stopPropagation()`) - ### Question1 當在文字上點一下時,所觸發的 click 順序,是 `<label>` 先?還是 `<input>` 先? - ### ChatGPT4 當你在包含 `input` 元素的 `label` 上點擊時,觸發的 `click` 事件順序通常是首先在 `input` 元素上觸發,然後是 `label` 元素。這是因為當 `label` 與特定的表單元素(如 `input`)關聯時,點擊 `label` 會自動將焦點和事件傳遞到相關的 `input` 元素。 這個行為基於 HTML 標準和瀏覽器的實現,目的是增加表單元素的可用性,尤其是對於視力不佳或使用屏幕閱讀器的用戶來說,點擊更大的 `label` 區域比單獨的小 `input` 元素要容易得多。 實驗驗證點擊順序 你可以通過下面的簡單實驗來觀察 click 事件的觸發順序: ```html= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Click Event Order</title> <script> function inputClicked() { console.log('Input clicked'); } function labelClicked() { console.log('Label clicked'); } </script> </head> <body> <label onclick="labelClicked()"> Click me: <input type="radio" name="option" onclick="inputClicked()"> </label> </body> </html> ``` 在這個例子中,當你點擊 `label` 內的文字或 `input` 時,你會在控制台看到打印的信息。從這個輸出你可以觀察到事件觸發的順序。 ### 注意 如果你在 `input` 的 `click` 事件處理器中使用了 `event.stopPropagation()`,則可以阻止事件繼續傳播到 `label`: ```javascript function inputClicked(event) { console.log('Input clicked'); event.stopPropagation(); // 阻止事件冒泡 } ``` 這樣就只會觸發 `input` 的 `click` 事件,而不會觸發 `label` 的 `click` 事件。這在某些需要精確控制事件處理順序和行為的場景下非常有用。 - ### Question2 為何點選 label 中的文字,會觸發 input 的 click 事件? - ### ChatGPT4 當你點擊一個包含 `input` 元素(如 `radio` 或 `checkbox`)的 `label` 時,會自動觸發相關 `input` 元素的 `click` 事件,這是由 HTML 標準中對於 `label` 元素的行為所定義的。這種設計主要是為了提高表單可用性,使得用戶能夠更容易地與表單控件互動,特別是在較小的螢幕或者使用輔助技術的情況下。 ### 原理解釋 當 `label` 與某個 `input` 元素關聯時(無論是通過將 `input` 放置於 `label` 內部,或者透過 `for` 屬性指定 `input` 的 `id`),點擊 `label` 會自動將事件傳遞給 `input`。具體行為包括: 1. **焦點管理**:點擊 `label` 會使相關聯的 `input` 獲得焦點。 2. **狀態切換**:對於開關型控件如 `checkbox` 和 `radio`,點擊 `label` 會切換其選中狀態。 3. **事件觸發**:點擊 `label` 會觸發相關 `input` 的 `click` 事件,這使得為 `input` 元素綁定的事件處理器可以被執行。 ### HTML 標準中的描述 根據 HTML 標準,當 `label` 被觸發(點擊)時,會執行以下步驟: - 如果 `label` 元素有一個 `for` 屬性,且該屬性的值是頁面上某個 `input` 元素的 `id`,則這個 `input` 元素會被觸發。 - 如果 `label` 元素不含 `for` 屬性,但包含一個或多個 `input` 元素,則點擊 `label` 會觸發最靠近 `label` 開始標籤的 `input` 元素。 ### 實際應用 這種行為允許開發者設計更加友好的用戶界面,特別是在表單元素較小或難以直接點擊的情況下。用戶可以簡單地點擊較大的 `label` 區域來進行選擇,無需精確點擊小的 `input` 控件,從而提高整體的用戶體驗。 <br> <hr> <br> ## iframe > spec: [4.8.5 The iframe element](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element) ### iframe 用法 - ### [HTML \<iframe\> 內嵌框架 (Inline Frame)](https://www.fooish.com/html/iframe-tag.html) <iframe width="100%" src="http://www.fooish.com/"> 你的瀏覽器不支援 iframe </iframe> <br> ### 來源提供者 - ### [被嵌入在 iframe 的我們如果顯示不出來要怎麼調整設定呢?](https://medium.com/%E7%A8%8B%E5%BC%8F%E8%A3%A1%E6%9C%89%E8%9F%B2/a0c5ce800bc2) > 以 Google 為例,打開網頁檢視工具,可以看到 Google 搜尋引擎的網頁 header 設定如下: > `X-Frame-Options: SAMEORIGIN` <br> ### iframe 使用者 - ### 測試 https://www.google.com 範例 - Response Headers - x-frame-options: SAMEORIGIN ![](https://i.imgur.com/F5WUitN.png) - www.google.com 拒絕連線 ```html <iframe id="google" src="https://www.google.com"></iframe> ``` [![](https://i.imgur.com/jYWfjRe.png)](https://i.imgur.com/jYWfjRe.png) - ### 測試 githubusercontent: html 範例 > 來源:[Plot classification probability](https://github.com/tsungjung411/jupyterlab-extension/blob/main/ml_examples/Scikit-Learn/Classification/plot_classification_probability.html) <iframe width="560" height="315" src="https://raw.githubusercontent.com/tsungjung411/jupyterlab-extension/main/ml_examples/Scikit-Learn/Classification/plot_classification_probability.html" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> - Refused to display 'https://raw.githubusercontent.com/' in a frame because it set 'X-Frame-Options' to 'deny'. ![](https://i.imgur.com/4PhUBLb.png) - ### [Github gist page won't load in iframe](https://stackoverflow.com/questions/7649361/github-gist-page-wont-load-in-iframe) > Github has added the X-Frame-Options: deny HTTP header, which prevents the page from being embedded in a page (such as a frame). ![](https://i.imgur.com/mst1pwX.png) - ### 測試 githubusercontent: image 範例 (OK) - [Embedding an image stored in github](https://stackoverflow.com/questions/52876285) ``` <img src="https://raw.githubusercontent.com/madelinekinnaird/Gerrymandr/master/images/az1.PNG" ``` ![](https://raw.githubusercontent.com/madelinekinnaird/Gerrymandr/master/images/az1.PNG) - ### [Set content of iframe](https://stackoverflow.com/questions/8240101) :+1: :+1: :+1: :100: ```javascript= var html_string= "content"; document.getElementById('output_iframe1').src = "data:text/html;charset=utf-8," + escape(html_string); ``` ```javascript= var html_string= "content"; document.getElementById('output_iframe1').src = "data:text/html;," + escape('Hello! My name is <b>Fzz</b>.'); ``` - "data:text/html," 這樣也可,總之要有 `,` - 原因在此 ![](https://i.imgur.com/IPLpwka.png) ![](https://i.imgur.com/Hb8k2Ee.png) - ### 完整程式碼 ```javascript function loadContentViaFetch(iframeId) { const iframe = document.getElementById(iframeId); console.log('iframe:', iframe); fetch(iframe.src) .then(response =>{ console.log('response:', response); if (response.ok) { response.text() .then(text => { iframe.src = buildHtmlContent(text); }).catch(function(errorObject) { console.log('errorObject:', errorObject); iframe.src = buildHtmlContent( '<b>'+ errorObject.message + '</b>' +'<br><pre>' + errorObject.stack + '</pre>'); }); } else { iframe.src = buildHtmlContent('<b>' + response.statusText + '</b>'); } }).catch(function(errorObject) { console.log('errorObject:', errorObject); iframe.src = buildHtmlContent( '<b>'+ errorObject.message + '</b>' +'<br><pre>' + errorObject.stack + '</pre>'); }); } function buildHtmlContent(content, charset=null) { var metadata = ''; if (charset) { metadata = `charset=${charset}` } return `data:text/html;${metadata},${escape(content)}`; } ``` - 看起來 charset 好像有編碼問題 - 沒用反而是正常 - ### 測試檔`test.htm` > **資料來源**:Scikit-Learn (sklearn) / Classification / Classifier comparison > - [from archive](https://scikit-learn.org/stable/_downloads/6f1e7a639e0699d6164445b55e6c116d/auto_examples_jupyter.zip) > - [from web](https://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html) > - 關鍵字:`# Code source: Gaël Varoquaux` > > <br> > > **說明**:用 charset 反而有編碼問題 > ```html= <iframe id="iframe1" style="width: 100%; height: 3em;"></iframe> <iframe id="iframe2" style="width: 100%; height: 3em;"></iframe> <iframe id="iframe3" style="width: 100%; height: 3em;"></iframe> <script> text = '<span># Code source: Gaël Varoquaux</span>'; iframe1 = document.getElementById('iframe1') iframe1.srcdoc = text; iframe2 = document.getElementById('iframe2') iframe2.src = 'data:text/html,' + escape(text); iframe3 = document.getElementById('iframe3') iframe3.src = 'data:text/html;charset=utf-8,' + escape(text); </script> ``` ![](https://i.imgur.com/B7n0JTQ.png) <br> <hr> <br> ## ruby ### ruby 緣由 - ### Question ``` <ruby> 私 <rp>(</rp><rt>わたし</rt><rp>)</rp> </ruby> ``` 日文漢字的假名,html 有 Ruby 語法可呈現,為何叫 ruby ? - ### ChatGPT4 `<ruby>` 標籤在 HTML 中用於呈現東亞文字的發音標註,特別是用於中文、日文和韓文等語言。這些標註通常顯示在文字的上方或下方,提供該文字的讀音或解釋。在日文中,這種格式被稱為振假名(ふりがな, furigana),主要用於給漢字標註平假名或片假名以指示讀音。 ### 為何叫 ruby? 名稱 "ruby" 的來源並不是因為寶石紅寶石(ruby),而是源於印刷和排版術語。在排版中,"ruby text" 是指出現在主要文字上方或下方的小字,用於註釋或解釋。這個名稱最初來自於英文排版術語,在英文排版中,“ruby”指的是一種小號的印刷字體,這種字體在過去曾經被用來印刷邊注或註釋。因此,當設計 HTML 標準來支持類似的文字標註功能時,這個術語被借用來命名 `<ruby>` 標籤標籤。 ### HTML 中的 `<ruby>` 標籤 `<ruby>` 標籤內部通常包括三種元素: - **`<rt>`(Ruby Text)**:用於包含每個基礎字符或字符組的發音或解釋。 - **`<rp>`(Ruby Parenthesis)**:用於在不支持 `<ruby>` 的瀏覽器中顯示括號,以便用戶能理解 `<rt>` 中的文本是註釋或發音。 例如,上述的 HTML 代碼: ```html= <ruby> 私 <rp>(</rp><rt>わたし</rt><rp>)</rp> </ruby> ``` 這在支持 `<ruby>` 的瀏覽器中會將 "わたし" 顯示在 "私" 的上方,如果瀏覽器不支持 `<ruby>`,則會顯示為 "私(わたし)",保證信息的可訪問性。这种方式提供了对文本的额外说明,帮助读者理解文本的正确读音或意义,尤其是在学习语言阶段非常有用。 <br> <hr> <br> ## span ### 容器內置中對齊 > - 行內元素:不受水平對齊屬性的影響 - ### Question ``` <span>123<br>abcdefghijk</span> ``` 要如何讓 `<br>` 上下兩段文字置中對齊? - ### ChatGPT4 要使 `<span>` 標籤內的文字,包括 `<br>` 標籤前後的內容,在水平方向上居中對齊,你可以使用 CSS 來達成這個效果。通常 `<span>` 是行內元素,它不會受到水平對齊屬性的影響。為了使內部的文字居中,你可能需要將 `<span>` 改為行內塊元素或塊級元素,並適用對應的對齊屬性。 以下是一個簡單的示例,展示如何設定 CSS 使 `<span>` 內的內容居中: ```html= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Center Text with Break</title> <style> .center-text { display: block; /* 將 span 轉換為塊級元素 */ text-align: center; /* 文字居中對齊 */ margin: auto; /* 自動邊距以在容器中水平居中 */ width: 100%; /* 寬度設為 100% */ } </style> </head> <body> <div> <span class="center-text">123<br>abcdefghijk</span> </div> </body> </html> ``` ### 解釋 CSS 屬性: - `display: block;`:將 `<span>` 從行內元素轉變為塊級元素。塊級元素會佔滿可用的水平空間,並允許我們設定寬度和自動邊距。 - `text-align: center;`:這個屬性會使得所有內部文本(包括 `<br>` 分隔的文本)在水平方向上居中對齊。 - `margin: auto;`:這樣設定邊距可以使塊級元素在其父容器中水平居中。 - `width: 100%;`:將寬度設為 100% 確保 `<span>` 充滿其父元素的寬度,這樣 `text-align: center;` 才能正確居中文本。 通過這種方式,你可以使 `<span>` 標籤內的內容在斷行後仍然保持居中對齊,適用於多種布局和設計需求。 <br> <hr> <br> ## textarea ### 變更文字後,textContent 屬性依舊 - ### Question ``` <textarea id="abc">123</textarea> ``` 為何在 textarea 變更文字,拿到的 textContent 卻依舊是 123 ? - ### ChatGPT4 當你在 HTML 中使用 `<textarea>` 標籤時,初始的文字內容通常是在標籤之間定義的。例如,在你的代碼中: ```html= <textarea id="abc">123</textarea> ``` 123 是 `<textarea>` 的初始內容。當你通過用戶界面改變 `<textarea>` 中的內容後,這些變化實際上是反映在 `<textarea>` 的 `value` 屬性中,而不是其 `textContent` 或 `innerText`。這是因為 `<textarea>` 元素特別地使用 `value` 屬性來存儲和檢索其內容。 因此,當你嘗試使用 JavaScript 獲取 `<textarea>` 中變更後的文字時,應該使用 `value` 屬性而不是 `textContent`。以下是如何正確做到這一點的例子: ```javascript= // 獲取 textarea 元素 var textarea = document.getElementById('abc'); // 正確的方式來獲取當前在 textarea 中的文字 var currentText = textarea.value; console.log(currentText); // 這將顯示用戶當前在 textarea 中輸入的文字 ``` 這段代碼使用 `document.getElementById()` 來獲取 `<textarea>` 元素,然後使用 value 屬性來讀取和輸出用戶當前輸入的文字,無論它是否已經被改變。 如果你使用 textContent 或 innerText,你會發現它們返回的是元素創建時的內容,而不是用戶當前的輸入,這在 `<textarea>` 的情況下通常不是你想要的結果。 <br> <hr> <br> ## case study ### TOKENS + CHARACTERS - ### Question1 <img src="https://hackmd.io/_uploads/SJMFGw8W0.png" style="border: 1px solid #000;"><br> 資訊是這樣: TOKENS 23 CHARACTERS 13 但我想把它 layout 成圖片所示 - ### Q1: ChatGPT4 看來你希望將文字資訊的佈局設計成上傳圖片中的樣式。圖片顯示了「TOKENS」和「CHARACTERS」的計數,它們被佈局成兩列,數字位於文字標籤的下方。 為了實現這樣的設計,我們可以使用 HTML 與 CSS。這裡提供一個基礎的範例代碼,你可以根據自己的需求進行調整: ```html= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Token and Character Count</title> <style> .count-container { display: flex; justify-content: space-around; align-items: center; font-family: 'Arial', sans-serif; color: #213547; } .count-block { text-align: center; } .count-number { font-size: 2em; margin: 0; } .count-label { margin: 0; } </style> </head> <body> <div class="count-container"> <div class="count-block"> <p class="count-number">23</p> <p class="count-label">TOKENS</p> </div> <div class="count-block"> <p class="count-number">13</p> <p class="count-label">CHARACTERS</p> </div> </div> </body> </html> ``` 在這段代碼中: - 使用了 `.count-container` 類別來創建一個 flex 容器,它會將子元素 `.count-block` 水平並排顯示。 - 每個 `.count-block` 包含一個數字(`.count-number`)和一個標籤(`.count-label`),並且將文本置中。 - CSS 被用來設定字體、大小、顏色等屬性,以符合你圖片中的設計。 如果你需要進一步的幫助或者有具體的設計需求,比如顏色、字體大小或者間距等,請告訴我,我可以提供更具體的幫助。 - ### Question2 詳細解說一下 .count-container 原理 - ### Q2: ChatGPT4 當然可以。.count-container 類別是一個 CSS 宣告,主要用於控制其內部子元素的布局和對齊方式。下面是詳細解釋: ```css= .count-container { display: flex; justify-content: space-around; align-items: center; font-family: 'Arial', sans-serif; color: #213547; } ``` - **`display: flex;`**: 這個屬性將元素設定為一個彈性容器。這意味著,其直接子元素將成為彈性項目(flex items),你可以使用 Flexbox 相關屬性來控制這些子元素的位置和對齐方式。 - **`justify-content: space-around;`**: 這個屬性定義了如何沿著彈性容器的主軸(在預設情況下為水平方向)分配子元素之間以及子元素與容器邊緣之間的空間。`space-around` 的值會導致子元素周圍有相等的空間。換句話說,每個子元素將有相同大小的空間在其兩邊,使得元素之間的間距看起來均等。 - **`align-items: center;`**: 這個屬性決定了子元素在彈性容器的交叉軸(垂直於主軸)上的對齐方式。設定為 `center` 表示所有子元素都會在容器的中心線上垂直對齐。 - **`font-family: 'Arial', sans-serif;`**: 這個屬性指定了容器內所有文字的字體。如果系統中安裝了 Arial 字體,則會使用它;如果沒有,則會回退到無襯線(sans-serif)的默認字體。 - **`color: #213547;`**: 這個屬性設定了容器內所有文字的顏色,這裡使用的是一個深藍灰色的色碼。 總之,`.count-container` 是用於定義一個水平布局,其中子元素平均分散並垂直居中對齐的彈性盒子模型。这种布局非常適合用來創建像是功能區、導航菜單或資訊展示卡等元素。 - ### Question3 如果我想讓 `TOKENS` 和 `CHARACTERS` 靠在一起,並置中,但中間只間隔 3em,要如何做? - ### Q3: ChatGPT4 為了讓 `TOKENS` 和 `CHARACTERS` 靠在一起並且置中,同時它們之間有固定的間隔(如 3em),你可以對 `.count-container` 類別和 `.count-block` 類別進行一些調整。以下是更新後的 CSS 代碼: ```css= .count-container { display: flex; justify-content: center; /* 讓子元素水平居中 */ align-items: center; /* 子元素垂直居中 */ font-family: 'Arial', sans-serif; color: #213547; } .count-block { margin: 0 1.5em; /* 每個 count-block 的左右外距設為 1.5em,兩個加起來正好是 3em */ text-align: center; } .count-number { font-size: 2em; margin: 0; } .count-label { margin: 0; } ``` 在這裡,我們使用了 `justify-content: center;` 來確保所有 `.count-block` 元素在 `.count-container` 中水平居中。`.count-block` 元素左右的外距(margin)設為 1.5em,這樣,當它們並排時,兩者之間的空隙會是 3em。 這個設定會將 `TOKENS` 和 `CHARACTERS` 兩個元素拉到一起並保持它們在容器中心的位置,同時它們之間會有一個固定的 3em 空隙。 - ### 背景知識 - [justify-content 屬性介紹](https://w3c.hexschool.com/flexbox/4a029043) <br> ### radio button - ### Question1 <img src="https://hackmd.io/_uploads/r14V6FP-A.png" style="border: 1px solid #000;"> 實作圖中三個 radio button 點文字也可以選 - ### [ChatGPT4] 要實作能夠點擊文字也能選擇的 radio buttons,你需要為每個 radio button 搭配一個 `<label>` 元素。這樣,當使用者點擊標籤中的文字時,相應的 radio button 也會被選中。這裡是一個基本的實現方式: ```html= <!-- 確保每個 radio input 的 name 屬性相同,這樣它們就會被視為一組 --> <form> <label> <input type="radio" name="option" value="text"> Text </label> <label> <input type="radio" name="option" value="tokenIds"> Token IDs </label> <label> <input type="radio" name="option" value="hide"> Hide </label> </form> ``` 這裡的每個 `<input>` 都被包含在一個 `<label>` 元素裡。當 ` 被點擊時,它會自動選擇或取消選擇其內部的 ` 元素。為了使 radio buttons 作為一組互斥選項工作,它們需要有相同的 name 屬性值。 如果你想要添加一些自定義樣式以匹配你的設計需求(比如上傳的圖片),你可以添加 CSS。以下是一個簡單的 CSS 樣式例子: ```css= /* 樣式化所有的標籤和內部的 radio buttons */ label { margin-right: 20px; /* 或你希望的任何間隔 */ cursor: pointer; /* 當鼠標懸停時顯示指針形狀 */ } /* 隱藏原生的 radio button */ input[type="radio"] { display: none; } /* 當 radio button 被選中時,使用一個自定義的圖標或背景來顯示它 */ input[type="radio"]:checked + label { background: url('checked_icon.png') no-repeat; /* 添加所需的 CSS 以正確顯示你的自定義圖標 */ } ``` 請注意,上面的 CSS 中用到了 `background: url('checked_icon.png') no-repeat;`,這需要你有一個選中狀態的圖標圖片。此外,實際的實現會根據你的具體需求和你所擁有的圖標或設計來調整。 這個例子並不包括實際的交互邏輯或 JavaScript,如果你需要幫助來實現這一部分(比如當選項改變時執行一些操作),請提供更多的信息或詢問具體的問題。