發表文章

JavaScript click 事件頻繁觸發?

圖片
之前在寫JavaScript的時候,不知為何很奇耙地搞出一個怪異的選取目標,並偶然發現它會因點擊目標父層的層數而觸發相對應的次數。 $(document).on('click',':not(#nav *)',function(e){ console.log('trigger'); }); 為了把這問題解決用很多種方法嘗試,結果只要多一行就解決了… $(document).on('click',':not(#nav *)',function(e){ if (e.target !== this) return; console.log('trigger'); }); click 和 touchend 一起用 另外一個寫不好的情況是 click 和 touch 事件一起用,造成兩個事件一起觸發。 $(document).on('click touchend','.toggle-button',function(e){ e.preventDefault(); $('#element').toggleClass('--active'); }); 解決的方法是增加一個 flag: var triggerFlag = false; var triggerThreshold = 200; $(document).on('click touchend','.toggle-button',function(e){ e.preventDefault(); if (!triggerFlag) { triggerFlag = true; setTimeout(()=>{ triggerFlag = false; }, triggerThreshold); $('#element').toggleClass('--active'); } }); 類似的頻繁觸發 另外在 scroll 和 resize 時,常常會因為頻繁觸發而導致效能爆...

還在用 Font Awesome 4? 趕緊放棄載入字體的 icon font

行動裝置預設阻擋 icon font 勢必會成為趨勢,除非你也有處理未載入時的畫面呈現,或有沒有icon對使用者的 UX 都沒有影響(這裡要捫心自問,既然有沒有 icon 都可以,為何還要放icon),否則只會有更多 browser 跟進如 firefox focus 這樣的瀏覽器或套件出現,就跟使用者主動安裝 adblock 是相同的道理。 Font Awesome 的升級 若你是使用 Font Awesome 且沒有時間處理這個問題,官方剛好有出一個快速解套的解決方案,讓開發者無痛從 4 升級到 5: Upgrading from Version 4 。 但這必需多載入  v4-shims.css  和  v4-shims.js ,對使用者而言就是多兩個 request ,所以有時間的話,還是全面改寫成正常的第5版會比較好,也就是不需要用CSS載入字體檔,只有JavaScript的版本(用JS產生SVG)。 就算第4版現在大部分的情況都能正常顯示,但由於 CSS 檔案肥大(因為包含字體檔),加上沒有 font-display: swap; 的語法,通常都會拖慢載入速度。所以,放棄需要載入字體檔的icon,投入 svg 的懷抱吧! 造成排版位移 網站若有使用其它字體 (例如 Google font) 的人都知道,就算有 font-display:swap 解決載入前後文字閃爍的情況,還是無法解決載入前後字體位移的問題,因為每種字體的大小與定位都有些微的不同。這個影響雖然不大,Google 強調的 CLS 看似也不把它當作問題,但這個問題確實存在。 還能更好 而前面提到直接貼<svg>的方式,難道第5版還不夠好嗎? 在 chrome 的 Lightinghouse 測試中,有無載入第5版的 Font Awesome 速度分數最多可以差到20分,Time to Interactive (TTI)更可以相差到 8 秒之多,若又選用有載入字體的CSS,分數又會差更多。所以才又提了直接放<svg>的方法,既少了一個 request,又不用載入 Font Awesome,TTI 也從 12 秒降到 4 秒,但開發上會麻煩很多。 在考慮使用者體驗和 SEO 的當下,網頁的載入當然是越快越好,但開發...

background-clip: text... bug in IE and old Edge

在 IE 和 Edge 中使用 display:flex 的情況下, background-clip ( -webkit- background-clip ):text 不會有作用。 拿掉 flexbox 就又能正常顯示… 如下面 codepen 中的範例:  See the Pen background-clip by cj ( @cjzopen ) on CodePen . html,body{ margin:0; padding:0; } div{ background-image:url(https://picsum.photos/1920/600/?random); background-size:cover; height:100vh; /*if display flex, background-clip will not working in ie and edge17 */ /*display:flex;*/ /*justify-content:center;*/ /*align-items:center;*/ /* fixed */ line-height:100vh; text-align: center; font-size:15vw; font-weight:700; background-clip: text; -webkit-background-clip: text; color: rgba(0,0,0,.2); position:relative; /* mix-blend-mode: difference; */ } div::after{ content:''; position:absolute; z-index:-1; left:0; top:0; width:100%; height:100%; background-size:cover; /*style1*/ /* Not all images are suitable for this gradient. You can change it. */ background-image:linea...

flexbox 子層在 width:auto 的情況下,flex-wrap:wrap 會失效 ( iphone6 safari)

圖片
在 iphone6 safari (版本更之前的iphone沒有實驗) 會出現以下情況才會出現,而 ipad 和其它瀏覽器順利地運作換行: flexbox 子層在 width:auto 的情況下,flex-wrap:wrap 會失效。 另外在子層 flex-grow:1 的情況下,在 IE 中,右邊的子層會直接蓋在左邊的子層上。 -- 解決: 子層 width:auto 拿掉,右邊改成 width:100%

Meta Description 會步入 Meta Keywords 的後塵嗎?

圖片
Meta Description (網頁描述) Meta Description  為搜尋結果中,網站標題下方的敘述說明,能讓使用者初步瞭解你的網站大概擁有什麼內容,這應該大家都知道。而如果你有在經營 Facebook 粉絲團的話,「品牌故事」就會是你的 Meta Description。 提外話,請不要把你的產品命名為 AirJordanShoe ,這樣使用者在搜尋 air、jordan、shoe 這三個任一關鍵字時, AirJordanShoe 並不會被搜尋結果 match。 濫用 常常在工作中被要求,或是偷看別人家網站原始碼時會遇到,把網頁描述當 Meta Keywords 使用,或是混在一起用 (這裡就不提把 一整群 keywords 塞在 title 的網頁了),大哥別鬧啦,小學生都會造句了,寫一段包含某些字的話很難嗎? 別忘了 網頁描述的功能:「 讓使用者初步瞭解你的網站大概擁有什麼內容 」。你能想像使用者看你的網頁描述是一堆沒有組織的單詞會做何感想嗎? 濫填關鍵字說明 誤導、欺騙 這點其實很少,大多是農場網站,其實短網址的詐騙更嚴重。 網頁描述的未來 所以 Meta Description 到底會不會步入 Meta Keywords 的後塵,在未來的某一天被google視為垃圾訊息?我們從兩點google對於網頁描述的政策來看吧。 自動產生 google對於沒有設定 或他們認為不好的 網頁描述之網頁,有可能會從網站內容中 截取後取代原本的網頁描述。 加長搜尋結果頁的網頁描述 從160字元增加到320字元,中文字的話一個字佔2~4個字元。 很顯然,因為網頁描述對 UX 來說太重要了,若將它視為垃圾訊息只會打google自己的臉。但也因為如此,對於網頁描述的評審機制將會越來越完善,說不定加到320字元只是截取技術改善前的暫時性措施,所以濫用關鍵字的網站在未來是不會得到好處的。 在之後不久,推論得到證實,Google馬上又改回160字元。 ----------------------------------------- 追記 而在2019年,google不斷強調Meta Description與網站排名並無直接關聯,只會影響「點擊意願」。換句話說,要先...

運用資料層 dataLayer.push 建立 GTM 自訂事件

圖片
GTM(Google Tag Manager;網頁代碼管理工具)最大的好處在於讓頁面較整潔、許多系統已經寫好的事件與變數可以直接拿來用,非常方便。但現實往往沒那麼簡單,通常都會遇到一堆 ajax、history 或 cache 要處理,這時候就要請到自訂事件出馬了。 若只用 GA,沒有使用 GTM 的話,自訂事件要這樣寫: gtag('event', ..., { 'event_category' : ..., 'event_label' : ... }); 那如果用 GTM 的話該如何操作呢? 將資料 push 進 dataLayer 首先我們要知道什麼是 dataLayer:一個 GTM 內部的全域變數,它能動態存取網頁的使用者行為數據。 更進一步探索它的   JSON   架構,可以在網頁上使用開發者工具(F12)的 console 欄,輸入 dataLayer,其實跟它的名字一樣就是層層分明的資料層 (Data Layer)。 在 F12 中查看 dataLayer 你會發現 GTM 測試欄位左邊有幾個事件,dataLayer 裡面就有幾個 object。 再把 object 點開(這裡以 Window Loaded 為例),會有 event 和 GTM 給的事件 id,而這個事件(gtm_load)其實就是「觸發條件」裡的「視窗已載入」。 因此,我們可以依樣畫葫蘆用 dataLayer.push 自己寫一段觸發條件把資料送進 dataLayer ,就可以在 GTM 裡面操作了: 開始設定自訂事件 先宣告 dataLayer,避免發生 undefined error 再設定你要 push 進去的數據 這裡我們用「 nav a 點擊偵測」和 ajax 事件舉例(jQuery): var dataLayer = window.dataLayer || []; // example 1: detect nav a tag click $('nav a').click(function(){ var $text = $(this).text(); dataLayer.push({ 'event'...

SEO 優化? 先談談其中的 SEF

圖片
什麼是 SEF ? SEF ( Search Engine Friendly ) 搜尋引擎友善,也有人稱之為 Technical SEO(技術 SEO)。簡單來說就是讓拜訪網站的機器人比較容易作業的技能,在 SEO 裡面只能算是冰山一角。 工程師在工作上常常被主管要求改善網站的 SEO ,卻不能改變其中的文字與圖片,這算哪門子的 SEO,頂多只能算 SEF。SEO 是較為全面的行銷,可以延伸到 PPC 、整體文案內容、社群經營、線下活動、UI排版、UX...都會對 SEO 造成影響。 對於說自己拚命改善 SEO 實際上只有做 SEF 的人,我真的不知道要怎麼溝通,因為 SEO 主要還是靠內容與其權威性。 扯遠了,還是回來看 SEF 吧。 HTML Meta tag title:網頁名稱。就如它的名稱,是這個網頁頁面的標題,也是在搜尋結果中呈現的名稱。 description:網頁描述,雖然在SEF中的比重極小,但還要要填。  property="og:xxx":Facebook 中呈現的樣貌。在台灣 FB 就是最大的社群網站,你不得不服。當然還有像是 twitter 之類的社群網站也有它們專用的 tag。詳見: The Open Graph protocol  和 twitter cards 。 以 SEF 的角度來說,title 和 description 這兩個是必要的,當然還有像是 charset、http-equiv、viewport 這些必要的東西,不過這三個會影響 RWD 的東西有誰不知道要加嗎? 你說 robots 跟 keywords 呢?基本上 robots 只有在你要下 nofollow 或 noindex、max-image-preview:large 的時候才會用到; 至於 keywords……都 2017 年了,別再考慮這個東西。 HTML Link tag canonical:指向的網頁,跟網頁權重有關。比方說,一個頁面有上百筆資料,你想一次呈現 10 筆,然後靠網址的變動程現不同筆的資料,這些網頁就需要加上這個避免流量分散。 另一個情況是「桌機、行動裝置」網頁,因為這兩頁內容相同,也必需加上這個 tag 指向其中一個主要的網頁,要不然會打架互相搶流量...

CSS 文字底線效果

用 box-shadow 實現 .text{ text-decoration: none; box-shadow:0 -1px 0 #2858aa inset; transition:box-shadow .2s ease-in-out; } .text:hover{ box-shadow:0 -1px 0 rgba(0,0,0,0) inset, 0 3px 0 #2858aa; transition:box-shadow .2s ease-in-out; } 結果如下 HOVER ME 用 psudo element 和 scaleX 實現 .text { text-decoration: none; position: relative; } .text::before{ content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 2px; background-color: #6ac7ef; transform-origin: bottom right; transform: scaleX(0); transition: transform .3s ease; } .text:hover::before{ transform-origin: bottom left; transform: scaleX(1); } 效果如下 HOVER ME

HTML table export to CSV

常常遇到上司想在網頁上方便觀看一些搜集而來的數據,之後又說想要把網頁上的表格匯出成 csv 檔案,方便他們用 excel 計算一些東西。這時候該怎麼辦才好? 以下為使用 jQuery 的解決方案 function exportTableToCSV($table, filename) { var $rows = $table.find('tr:has(td)'), // Temporary delimiter characters unlikely to be typed by keyboard // This is to avoid accidentally splitting the actual contents tmpColDelim = String.fromCharCode(11), // vertical tab character tmpRowDelim = String.fromCharCode(0), // null character // actual delimiter characters for CSV format colDelim = '","', rowDelim = '"\r\n"', // Grab text from table into CSV formatted string csv = '"' + $rows.map(function(i, row) { var $row = $(row), $cols = $row.find('td'); return $cols.map(function(j, col) { var $col = $(col), text = $col.text(); if(/^(0)([0-9]){9}/.test(text)){ return '=""'+text...

DevTools (Chrome 59 更新)

圖片
TL;DR CSS and JS code coverage  可以看 js 與 CSS 未使用的比例,程式碼行數旁邊也會有紅綠區隔。 Full-page screenshots  全版網頁截圖。 Block requests  隔離呼叫的檔案。例如某支CSS 檔,可以看少了這個檔案頁面呈現的情況。 Unified Command Menu  Command Menu ( Ctrl Shift P ) 的更新,這個可能看影片比較快。 *下文多次提到的  Command Menu 快捷鍵為 ctrl + shift + p CSS and JS code coverage 在 Command Menu 輸入 show coverage,然後按下開始 ( 圓形 icon ) ,過一段時間按下停止就可以了。 show coverage Full-page screenshots 這個功能讓長網頁截圖不再是件麻煩事,在 Command Menu 輸入 Capture full size screenshot ( 如下圖 ),Chrome 就會開始下載整個網頁的截圖了,不過不知為何它把此指令分類為 mobile。 Full-page screenshots Block requests 切到 Network 介面,在想要阻檔的檔案上按右鍵選擇 Block request URL ,之後重整頁面就可以了。 Block requests 來源為  Google developers  4 月份的文章。

如何使用 HTML 的 picture 元素

圖片
<picture> 是 HTML5 包覆圖片用的 tag。可以搭配 source 來因應不同情況下(解析度、寬度),甚至是相容性(webp、jpg、svg、png……)來顯示的圖片。 現況 基本上所有的瀏覽器都支援此 HTML5 的 tag,除了 IE ( Edge )系列要更新到 Edge 13 之後的版本才能使用。不過就算不支援也只是回到原先的 img 而已,沒有什麼大礙。 使用方法 不同的圖片類型: <source srcset="img/text.avif" type="image/avif"> <source srcset="img/text.webp" type="image/webp"> 不同瀏覽器寬度: <source media="(min-width: 768px)" srcset="text-768.jpg"> <source media="(min-width: 360px)" srcset="text-360.jpg"> picture 會由上到下找尋吻合瀏覽器現況的 source 值,若第一個 source 值不符合使用的瀏覽器的支援度,才會去找第二個、第三個……,以此類推,都不適用才會直接套用原本寫在 img 的圖片。 實例 <picture> <source media="(min-width: 1440px)" srcset="https://api.fnkr.net/testimg/1920x400/9a91f2/FFF/?text=min-width-1440px"> <source media="(min-width: 768px)" srcset="https://api.fnkr.net/testimg/1440x300/c7254e/FFF/?text=min-width-992px"> <img src="https:/...

border animate (hover)

HTML如下: <section class= "box" >      <div class= "boALL" > </div> <!-- all borders --> <div class= "boTop" ></div> <!-- 上 --> <div class= "boRight" ></div> <!-- 右 --> <div class= "boBottom" ></div> <!-- 下 --> <div class= "boLeft" ></div> <!-- 左 -->      <a href= "javascript: void(0)" class= "txt" > HOVER HERE </a> </section> css setting: .box {    display: inline-block ;    width: 200px ;    height: 60px ; background-color: #999 ;    position: absolute ;    left: 0 ;    right: 0 ;    top: 0 ;    bottom: 0 ;    margin: auto ; text-align: center ; line-height: 60px ;    transition: background-color .7s ; } .box:hover { background-color: #...

clock (hands)

HTML架構如下(html structure): <div class=" clock ">     <div class=" centerDot "></div>     <div class=" secHand "></div>     <div class=" minuHand "></div>     <div class=" hourHand "></div>     <div class=" number1 number ">1</div>     <div class=" number2 number ">2</div>     <div class=" number3 number ">3</div>     <div class=" number4 number ">4</div>     <div class=" number5 number ">5</div>     <div class=" number6 number ">6</div>     <div class=" number7 number ">7</div>     <div class=" number8 number ">8</div>     <div class=" number9 number ">9</div>     <div class=" number10 number ">10</div>     <div class=" number11 number "...