顯示具有 Html CSS 標籤的文章。 顯示所有文章
顯示具有 Html CSS 標籤的文章。 顯示所有文章

2024/02/17

【新手必看】CSS Grid 排版主畫面,從零到一教學!

作者:吳祐賓





在我的【Delphi in Depth DataSnap 網站應用程式全端開發】一書裡提到,主畫面的製作會使用 東西南北中(EWSNC)的版面配置。這是由於網頁前端沒有像 WinForm framework 般有內建制式的版面配置,若要實現類 WinForm 版面配置就要借助 Layout 概念元件來實現,在 EasyUI 中採用【Layout 布局】,在 ExtJS 則採用 【Border Layout】。

EasyUI Layout 布局

ExtJS Border Layout



傷腦筋,使用多組三方元件時 CSS 就必打架

EasyUI 和 ExtJS 他們都屬於 JavaScript 應用程式框架,他們的差異在於:

  • EasyUI:jQuery 為核心的可佈局元件組,也可讓 Angular, VUE, React 等框架使用
  • ExtJS:MVVM 為設計概念的 JS 框架,從佈局到小元件的使用採一條龍式的完整框架

不論是哪一種,只要使用完整的三方元件解決方案, 他們大多會控制到最底層的 CSS 顯示效果,進而造成彼此間的 CSS 或多或少互相干擾的情形。所以可能的話還是要自己試著寫寫看 CSS Layout,來減少干擾的可能。

自己做 Layout 如何?

Layout 要自己做而不用元件,這很有挑戰性,目標先定在把東西南北中建立起來,至於可隱藏、自由調整寬度等功能就先忽略。

之後就來看看僅用 HTML 和 CSS 如何建立 Border Layout。

HTML

東西南北中佈局,從字面上來看可以知道會有五個格子,HTML 可以寫成以下內容,實際呈現時可以發現它們會從上到下排列。

  <div class="container">
    <header></header>
    <nav></nav>
    <main></main>
    <aside>西</aside>
    <footer></footer>
  </div>



"header" 標籤顧名思義就是佈局最頂端的位置,通常會設立標題在此處。"nav" 標籤用於導覽及連結,常見的是 Tree 元件。"main" 為中間的主要顯示區塊。"aside" 放側邊欄或額外內容。"footer" 放在佈局最底端的內容,通常用於版權宣告。



CSS

東西南北中的佈局方式相當制式,類似於表格,所以可以使用 CSS Grid 排版法進行處理。由於呈現"東西中"及"南北中"交錯,所以 Grid 設為 3 x 3 的方式進行排版。"container" 為圖層最底端,決定在它之上的圖層要怎麼排版。按底下的 CSS 設定完成後應該會像下圖顯示的那般好看。

.container {
  display: grid;
  grid-template-columns: 16rem 1fr 16rem;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "nav content sidebar"
    "footer footer footer";
  min-height: 100dvh;
}

header {
  grid-area: header;
  padding: 2rem;
  background-color: #C5E1A5;
}

nav {
  grid-area: nav;
  padding: 2rem;
  background-color: #90CAF9;
}

main {
  grid-area: content;
  padding: 2rem;
  background-color: #F48FB1;
}

aside {
  grid-area: sidebar;
  padding: 2rem;
  background-color: #FFAB91;
}

footer {
  grid-area: footer;
  padding: 2rem;
  background-color: #FFF59D;
}  




"container" 在 "中" 的區塊都用 1fr 將所有剩餘空間給它。關鍵在 "grid-template-areas" 區塊排版內容,這裡使用硬編碼將 3 x 3 的區塊都寫上去,雖然囉嗦了點,但一看就知道整個版型大概的模樣。其它標籤定義 "grid-area" 區塊名稱,grid-template-areas 就是按照 grid-area 進行排版的。

加入 RWD 吧!

既然都自己刻 CSS 了,自動適應畫面也順便一起加上去,就加入手機大小的 RWD 處理。因為手機畫面屬於寬度較短,高度較長,所以就使用由上到下排列的方式進行排版。由於有五個區塊,且資訊顯示的權重也不一樣,所以高度的呈現也有所調整。最後使用 "grid-template-areas" 決定手機版面顯示區塊的順序。畫面應如下顯示。

@media (max-width: 1024px) {
  .container {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(5rem, auto) 1fr minmax(5rem, auto) auto;
    grid-template-areas:
      "header"
      "nav"
      "content"
      "sidebar"
      "footer";
  }
}





"grid-template-rows" 對於"東"、"西"兩個區塊使用 minmax(5rem, auto) 限制它最小高度為 5rem,最大高度為 auto。

總結

本篇文章主要講述使用三方廠商的排版解決方案時,可能遇到因為 CSS 設定底層顯示方式不同而產生的衝突問題。若是底層沒有很複雜,自己寫排版畫面或許可以減少三方廠商元件的衝突問題。至於如何開始,這篇的教學內容相信可以讓你很快速地從 0 到 1 排出心目中理想的畫面。

和你分享

See also


2021/05/25

EasyUI Form 讀取 API 的知識點

 

EasyUI Form 事件流程
EasyUI Form 事件流程

從原生到三方元件

HTML 原生的 Form 使用上很容易,原本也要採用這樣的設計,但為了界面一致性,採用 EasyUI Textbox 等元件配置,但 EasyUI 元件實際在渲染時會和我們預期配置不同,這也造成上傳時有些要注意的地方。例如設計的 input class="easyui-passwordbox" 就會被拆成兩個 Html 標籤處理:

2021/05/14

那些在 HTML 畫 Banner 的小事


在網頁復刻應用程式時,第一關面對的是 UI 重建,而最先遇到的就是介面橫幅 (Banner)。

在重建的過程中,難免會把以前的開發套路帶進來,造成時間上的浪費。

橫幅解構

要重建橫幅,就要先解構它成為一個個小零件,再重組起來,內容如下:

  • 漸層方塊
  • 主標題
  • 子標題

一共三個元件,我是這麼處理的。

2020/08/14

The SameSite attribute of the Set-Cookie in WebBroker Response

前陣子在陪好友練習 Cookie 操作時,無意間發現瀏覽器跳出一個奇怪的警告訊息:

一查才發現原來是瀏覽器為了防止儲存的 Cookie 被送到其它網站服務器所作的安全機制。

若現在不理它,未來可能會被瀏覽器無視,所以先來了解要如何解決。

2020/08/08

跨來源資源共用CORS處理方式(一)

 

寫對外公開 WebAPI 時,會因為瀏覽器安全性的關係而禁止非同源存取。

如以下範例:

2020/01/17

form + API 的兩種方式比較

一個 form post 也可以繞個一大圈


網頁傳統 form 要傳遞參數值時,會使用 action,寫法大致如下:

  <form action="http://localhost:8080/login" method="post">
    <h1>Form Action Test</h1>
    <input type="text" name="email" value="Eden" />
    <input type="password" name="password" value="L@veEden" />
    <input type="submit" value="Submit">
  </form>

可以看到 submit 時,Request 的 Content-Type 屬性是很標準的 application/x-www-form-urlencoded。



這個方式很標準,絕大部份的 Web Server 都可以接受,當然也包含了 Delphi Web Server。

時代在進步,JavaScript 標準都來到 2020,所以當然要試一下新的操作方法。

JavaScript 裡有 FormData 類別,可以建構 form 物件,寫法如下:

  <form id="login-form" onsubmit="handleSubmit(event)">
    <input type="text" name="email" value="Eden" />
    <input type="password" name="password" value="L@veEden" />
    <input type="submit" value="Submit">
  </form>
  
  <script>
  function handleSubmit(event) {
    event.preventDefault()
    let formData = new FormData(document.getElementById('login-form'))

    fetch("http://localhost:8080/login", {
      method: "POST",
      body: formData
    })
  }
  </script>

實際 submit 時 Request 的 Content-Type 屬性是 multipart/form-data,如下圖所示:




multipart/form-data 相對於 application/x-www-form-urlencoded 比較少見,故某些 Web Server 預設是不會處理 multipart/form-data 的格式內容。

既然後端需要做調整,如果前端事先做好,那後端不就更省事?

前端調整

仿照傳統規則

前端仿照傳統的作法實作,程式碼如下:

  <form id="login-form" onsubmit="handleSubmit(event)">
    <input type="text" name="email" value="Eden" />
    <input type="password" name="password" value="L@veEden" />
    <input type="submit" value="Submit">
  </form>
  
  <script>
  function handleSubmit(event) {
    event.preventDefault()
    let formElement = document.getElementById("login-form")
    let formData = ""
    formData = "email=" + formElement[0].value
    formData = formData + "&password=" + formElement[1].value
    fetch("http://localhost:8080/login", {
      method: "POST",
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      body: formData
    })
  }
  </script>

執行結果


修改後就能讓 Web Server 順利解析參數。

使用 URLSearchParams

URLSearchParams 是個處理各種URL查詢參數轉換的類別,在這個例子只需要將 FormData 再丟入 URLSearchParams 處理過,即能得到 application/x-www-form-urlencoded 所需的查詢參數,程式如下所示:

<html>
<head></head>
<body>
  <form id="login-form" onsubmit="handleSubmit(event)">
    <input type="text" name="email" value="Eden" />
    <input type="password" name="password" value="L@veEden" />
    <input type="submit" value="Submit">
  </form>
  
  <script>
  function handleSubmit(event) {
    event.preventDefault()
    let formData = new FormData(document.getElementById('login-form'))
    var searchParams = new URLSearchParams(formData);
    fetch("http://localhost:8080/login", {
      method: "POST",
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      body: searchParams
    })
  }
  </script>
</body>
</html>

執行結果


一樣修改後就能讓 Web Server 順利解析參數。


總結

新方法但沿用舊觀念,在某些前端框架看不到的細節還是要拆成香草JS小部件來多做嘗試才行。

前端修改下我會偏好使用 URLSearchParams,在開發上比較省力,程式也比較好懂。

以上提供各位參考。謝謝大家收看!


【2021.05.18 更新】

jQuery 和 form 的結合


<html>
<head>
  <script
  src="https://code.jquery.com/jquery-3.6.0.js"
  integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
  crossorigin="anonymous"></script>
</head>
<body>
  <form id="login-form" onsubmit="handleSubmit(event)">
    <input type="text" name="email" value="Eden" />
    <input type="password" name="password" value="L@veEden" />
    <input type="submit" value="Submit">
  </form>
  
  <script>
  function handleSubmit(event) {
    event.preventDefault()
    const formData = {user:document.getElementByName("user").value, password:document.getElementByName("password").value}
	
	// item 的內容也可以用 $.ajax.beforeSend 替換
	const item = {
		'url': "http://localhost:8080/login",
		'type': 'POST',
		'headers': {
		  'Authorization': `Basic ${ base64Auth }`,
		},
		//'contentType': false, // Default = application/x-www-form-urlencoded
		//'processData': false, // false = jq 不轉譯 Json to Parameters; Default=True
		'data': formData
	}

    $.ajax(item)
      .done(function (response) {
        console.log(response)
      })

      .fail(function (response) {
        console.log('Fail : ' + response.responseText)
      })
  }
  </script>
</body>
</html>


2018/07/08

JavaScript iframe Variable Scope Test


目的:
測試 JavaScript Variable 在重複載入時是否共用同一個 Variable。

測試方式:
建立多個 iframe,但指向同一個 html 檔案。

JavaScript code is below:

  var MyVar = 0;
  function onButtonClick() {
    $("#A1").html(MyVar);
    MyVar += 1;
  }


預期:載入 base.html 時,MyVal 會預設歸零,藉以測試其它重複載入的 iframe 裡的同名變數是否會被影響。

測試步驟:
1. 建立 iframe 並累加 5 次變數
2. 以再建立 iframe 的方式重複載入該 html 檔案
3. 回到原 iframe,再累加變數,檢查變數是否歸零
4.切換到 2. 所建的 iframe 並累加變數,檢查變數是否被 3. 累加

結論:
各別的 iframe 就算是載入相同 JavaScript 檔,裡面同名 Variable Scope 也僅限在該 iframe 裡。

結果符合預期,收工。



See also :



2017/12/25

JavaScript 動態載入 JavaScript (CHT)

在載入 ExtJS 這種大型 JS 框架時,如果 Client 端網路速度不夠快,在首次載入時會空白畫面等很久,為了讓用戶端有更好的體驗,所以還是要有個進度條來刷個存在感,如此一來用戶也比較願意在自己的網站停留比較久的時間。

以下是程式碼範例:

2012/08/20

IE Table 專用的 "bordercolordark" 和 "bordercolorlight"

 參考了以下的網頁:
http://w3help.org/zh-cn/causes/BT3003
http://help.dottoro.com/lhcrketd.php

知道這兩個屬性是IE專用的屬性,微軟也說不要再用它了,但卻也沒提到如何解決。

所以參考了 Dorroto 網頁的寫法:
// top right bottom left
    // blue cyan cyan blue
<table style="border:4px solid; border-color:#0000FF #00ffff #00ffff #0000FF;">
    <tr>
        <td onclick="ChangeBorder ();">Click this text!</td>
    </tr>
</table>


border-color 的配置順序是:上 左 下 右
所以要達成配色的話會是:色1 色2 色2 色1

但TD標籤並不會影響,那怎麼辦呢?

所以還需要再加上

<td style="border-color:#00FFFF #0000FF #0000FF #00FFFF;">Click this text!</td>
也就是反過來:色2 色1 色1 色2