Biểu tượng website Khó ăn cát bê tông

Tác giả: Kacbt

Giải quyết vấn đề permission của NodeJS

Bạn sử dụng hệ điều hành Linux để phát triển phần mềm ứng dụng trên môi trường NodeJS và rất bực mình khi thường xuyên bị báo lỗi với quyền liên quan NodeJS hoặc có những cảnh báo cảm thấy không lấy gì làm vui vẻ, tích cực cho lắm? Bài viết này chia sẻ phần nào cách KACBT đối mặt với vấn đề, có thể bạn tìm thấy sự hữu ích, áp dụng được.

Chưa cài NodeJS muốn cài từ đầu, không dùng root

Ghé vào trang https://nodejs.org/download/release để tải phiên bản Node.js bạn muốn dùng để tải về dưới dạng file .tar.gz

Thực hiện các lệnh sau:

Các lệnh cài đặt Node.js với user thường

Sau cùng, hãy kiểm tra thành quả của bạn xem đã ổn chưa với lệnh node –version

Bạn tự do thay đổi node-v18.14.0-linux-x64.tar.gz bằng phiên bản Node.js của bạn, thư mục nodejs-apps bằng tên thư mục do bạn tự đặt nhé.

Đã có Node.js trên máy, muốn thay đổi thành user bình thường

Thực hiện lệnh npm config get prefix để xem có phải hiện ra /usr hay không? Nếu đúng, thực hiện tiếp các lệnh sau:

Cài Node.js global cho user thường

Cách này có hai điều cần lưu ý:

Nếu trước đây bạn đã phải dùng root để cài đặt các modules và có app nào đó đã chạy thì rồi sẽ báo bạn không có quyền. Cách xử lý: sudo chown -R whoami ~/.npm && sudo chown -R whoami /usr/local/lib/node_modules

Để có thể lần khởi động máy sau, các thiết lập trên vẫn còn tác dụng, bạn phải có lệnh: echo -e “export NPM_CONFIG_PREFIX=~/.npm-global\nexport PATH=\$PATH:~/.npm-global/bin” >> ~/.bashrc

Sử dụng NVM (Node Version Manager) khi bạn muốn khác bên trên

Cách này tất nhiên lúc ban đầu cần mất chút thời gian để làm quen, sử dụng. Nhưng lợi ích lâu dài của nó là xứng đáng với những gì bỏ ra.

Vào trang https://github.com/nvm-sh/nvm xem phần Installing and Updating và làm theo, hết sức dễ dàng, bạn có thể xem chỉ với vài câu lệnh:

Sử dụng NVM để quản lý các phiên bản Node.js

Đây là cách đáp ứng tốt nhất các yêu cầu phức tạp về Node.js khi cần sử dụng nhiều phiên bản khác nhau, các gói cài đặt khác nhau của ứng dụng cần phiên bản khác nhau tránh “giẫm đạp” lên nhau thành một mớ hỗn độn mất kiểm soát.

Đăng tại Chưa phân loại

Tại sao IT, lập trình không dễ ăn, lắm mơ mộng

Bài này đăng lại comment từ một status Facebook do chính tác giả comment trên group Facebook mang tên Học lập trình web (F8 – Fullstack.edu.vn). Tại sao đăng lại? Tại vì thấy có vẻ như nhiều bạn trẻ (và không còn quá trẻ nữa khi ở tuổi 26 đến 32) mà lại hay hỏi những câu rất lơ ngơ. Có thể một trong số đó vô tình vào KACBT để học HTML, sẵn đọc luôn cho bớt mơ mộng.

Vấn đề của những bạn mơ bước chân vào lập trình là gì?

Vấn đề lớn nhất của những người không đủ tiêu chuẩn để gia nhập nghề mới dù loay hoay nhiều năm, học lung tung cả lên hết trung tâm nọ, trung tâm kia, mua hàng chục khóa học online với giá khoảng 9 đến 99 đô la.

Gần đây, tui vô tình nghe một Podcast về những người học lập trình kiểu mì ăn liền. Podcast đó phản ánh một thực tế rằng nhiều kẻ mơ mộng, suy nghĩ khá hời hợt về nghề lập trình.

Mấy cái KHÔNG sau cần giải quyết hoặc khắc phục phần lớn thì tiêu chuẩn nghề mới nâng cao lên được, mới có thể đi làm.

  • Tiếng Anh yếu kém: cái này đánh rớt hết 80% những người mơ mộng muốn chuyển sang làm trong lĩnh vực lập trình, hay nói đúng hơn, chưa tới được bãi gửi xe lấy gì mà tham dự sự kiện?
  • Người học không chịu kết bạn ngoài đời, không đi chơi giao lưu với dân trong nghề để học hỏi, không mò đến các event về ngành định chuyển qua để được tắm trong không khí của nó, để hít thở, ngửi mùi, kích thích sự hứng thú với nghề mới. Trong khi đó toàn lên mạng tám với dân ngoại đạo, showbiz của nghề hơn là dân trong nghề. Dân trong nghề thực thụ lại ít tám trên mạng, có tám họ toàn vô những chỗ khá chuyên sâu.
  • Tạp chí chuyên ngành là “vũ khí” rất quan trọng để tìm hiểu, học hỏi, nghiên cứu một chuyên môn mới nhưng hầu hết thanh niên Việt Nam (trừ những HS, SV từng làm nghiên cứu khoa học ở trường/ đại học hoặc bị thầy cô giáo bắt tìm đọc tạp chí để làm bài tập/ đề tài nghiên cứu) KHÔNG biết tạp chí chuyên ngành là gì, ngay cả dân đang trong nghề còn chưa biết đến có sự tồn tại của chúng, mà lại cho rằng chúng kém hữu ích, và hẳn họ chỉ ở mức thợ code là hết mức.
  • Người học sợ, ngại đọc sách và cũng sợ tham gia các khóa học dạng MOOC đủ chuẩn SCORM hoặc AICC mà chỉ thích xem clip, đọc các tut, xem video clip, học mót các course dạng bootcamp mà người hướng dẫn không có chứng chỉ về sư phạm giảng dạy.

Đặc điểm của nghề mang tính kỹ thuật/ ứng dụng như IT, lập trình

Ngành kỹ thuật khác nhiều so với các ngành xã hội đó là phải đề cao tính chất làm để học chứ không phải học để làm. Cho nên, người học phải nhúng tay vào làm mới học được. Ai có tư tưởng học lý thuyết cho nhuyễn rồi mới thực hành là hỏng, hỏng bét, hoặc chỉ học thực hành, xao nhãng lý thuyết cũng hỏng. Hai món này phải đan xen, cài vào nhau trong mỗi buổi học thì mới là cách học phù hợp.

Ví dụ như để làm được giao diện trang web thì phải lôi “đồ nghề” là trình soạn thảo văn bản thô, thu thập các file hình ảnh (được thiết kế trên Photoshop, tìm kiếm trên mạng, kho ảnh trước đó) rồi ngồi mà lắp chúng lại, trong quá trình lắp sẽ phải thì đọc “tài liệu hướng dẫn”, không khác so với lấy bộ đồ chơi lắp ghép Lego ra chơi.

Để học được vào, được thấm, hiểu rõ, khi học người học cần phải ép bản thân mình vào tư thế không thoải mái, tránh rơi vào giấc ngủ hoặc dễ bị xao nhãng bởi mấy thứ linh tinh. Bạn có thể tham khảo một cô bác sĩ người Anh nói về việc này.

Ví dụ: kiếm một cái màn hình mà 25 phút nó tắt một lần, 5 phút sau mới lại bật lên được thì ta sẽ thấy 25 phút rất quý báu, tranh thủ mà cày cho xong đoạn code nào đó tránh để màn hình làm cho mất hứng. Bàn phím thì nên mua một cái second-hand tiếng Nhật để buộc phải thuộc cách gõ code, bởi việc nhìn mặt phím là vô dụng. Tất nhiên, bạn đừng ngây thơ nghĩ rằng có cái màn hình nào mua mới ngoài tiệm có sẵn chức năng 25 phút tắt một lần. Cách học là bạn phải suy nghĩ vấn đề, tìm kiếm phần mềm trên máy tính để thực hiện chức năng đó cho bạn.

Kết: Khắc phục được các vấn đề trên, việc chuyển sang nghề viết code là trong tầm tay các bạn.

Đăng tại Chưa phân loại

Bài 8: thêm chi tiết cho web trà sữa

Trang web trà sữa đã tạm ổn nhưng có gì đó vẫn cần phải mông má, trang điểm thêm để cho có vẻ là tui cũng biết làm web, có phải vậy? Bài này sẽ thêm một số thứ trang trí hoa lá cành chơi.

Trong quá trình trang trí, chúng ta không chỉ có thêm, mà còn có “đập bỏ”, xoá, sửa các kiểu. Việc này chủ yếu là để có dịp thực hành, quậy phá vì chúng ta đang học, và học để làm chơi.

Nếu bạn định dấn thân vào làm web kiếm cơm như một nghề, bạn cần phải phác thảo kế hoạch bài bản, khi bắt tay làm là làm theo các bước chặt chẽ, kỷ luật, vì làm kiểu nghiệp dư khó có thể có thu nhập ổn.

Bạn hết sức tránh việc vừa làm đến bước N rồi lại không đi được tiếp tới X, Z mà lại quay về đập bỏ, sửa chữa quá nhiều ở bước E, F nào đó.

Hãy cho chúng tôi xem trang web của bạn

Nếu tự học bằng cách chỉ xem người khác làm và làm theo mà không có ai để trao đổi, một số người thấy rằng họ không biết mình đang tiến bộ hoặc kém cỏi như thế nào.

Trong thực tế, có một số bạn trẻ còn sử dụng cụm từ “mông lung như một trò đùa“. KACBT cho rằng đùa hay không chẳng phải là điều quan trọng. Bạn có thể gửi trang web bạn làm từ bài 1 cho đến lúc này để chúng tôi để chúng tôi xem qua và có vài nhận xét.

Việc gửi này có hơi rắc rối bởi vì chúng tôi cũng mong rằng bạn biết sử dụng tin học văn phòng, kỹ năng truy cập Internet chứ không phải là dạng ngáo ngơ. Do đó, cách làm là nén thư mục web của bạn lại, đưa lên Google Drive, sau đó, báo cho chúng tôi biết ở phần Liên hệ.

Web trà sữa của KACBT trông khá buồn cười sau:

Sau khi xem trang web của bạn, chúng tôi sẽ phản hồi qua email và có một bản nhận xét tại khu vực thảo luận để những người khác có thể tham khảo, bình luận.

Trang web trên bạn không thấy có hình ở giữa trang, bên dưới Đang được yêu thích bởi vì lý do trong mã HTML sử dụng file ảnh PNG nhưng ảnh thực tế chúng tôi có lại là ảnh JPEG có đuôi .jpg. Trình duyệt sẽ hiện lên các dòng chữ ở thuộc tính alt của thẻ IMG. Sửa tên file ảnh là xong:

Lưu file, bấm phím F5 khi đang xem bằng trình duyệt sẽ thấy ảnh hiện lên. Nếu bạn có hình là PNG, đừng làm gì thêm.

Cải tiến trang web như thế nào?

  1. Tìm kiếm một giao diện trang web nào đó mà bạn thích, tốt nhất là cũng 3 cột, có header và footer. Mới đầu, bạn cần tìm giao diện khá đơn giản thôi, đừng lấy các trang quá phức tạp để học theo vì sớm làm bạn bỏ cuộc vì độ khó. Làm việc này nếu bạn không thể nghĩ ra nên làm gì tiếp theo với web hiện tại.
  2. Cố gắng tra cứu, áp dụng những thuộc tính CSS vào trang web hiện tại để nó trông bắt mắt hơn. Những thuộc tính này sẽ liên quan đến font chữ, hình ảnh, màu nền hoặc ảnh nền. Cũng thêm nội dung vào để cho có vẻ gì đó giống 1 trang web trong thực tế.
  3. Tìm kiếm những chủ đề trên mạng hướng dẫn cụ thể xử lý một vấn đề nào đó bạn đang muốn cải tiến, đọc vài chủ đề như vậy và áp dụng vào trang web của bạn.

KACBT cải tiến trang web trà sữa theo các bước như sau:

Save bai7.html thành bai8.html, bai7.css thành bai8.css và sửa dòng nhúng stylesheet ở phần HEADER trong file bai8.html thành bai8.css để tách biệt với bài trước.

Khi cần bạn có thể xem lại, so sánh, đổi chiếu để nắm bắt được việc học thay đổi, tiến triển như thế nào qua từng bài.

Thêm vào sau class .header trong file bai8.css đoạn:

Thêm bên dưới class .left-nav đoạn:

Ra kết quả trông như sau:

Chỉnh CSS font chữ
Trà sữa ánh sao banner

Thử bo góc cho các hình ảnh ly trà sữa với đoạn mã CSS:

Khi rà chuột lên hình ly trà sữa, cho ảnh đổi màu xem sao?

Chỉnh cho FOOTER canh giữa dòng địa chỉ quán trà sữa:

Cải tiến CSS riêng cho TABLE

Table bảng giá trà sữa, trông giao diện như này:

Chỉnh cỡ font, màu chữ cho tiêu đề của bảng:

Các dòng trong bảng dày, ít khoảng hở, trông kém thoáng đãng, ta dùng CSS sau:

4 dòng cuối cùng trong hình trên là để chỉnh canh giữa dòng chữ cột 1 và cột 3 trong bảng.

Chỉnh CSS dành riêng cho FORM

Giãn dòng (tức các DIV) trong FORM, dùng CSS:

Chỉnh cho dòng chữ Form đặt món của FORM đậm lên để dễ nhận biết:

Thử dùng công cụ hỗ trợ viết CSS

Trên mạng có rất nhiều công cụ hỗ trợ việc viết CSS dễ dàng hơn. KACBT xin giới thiệu một công cụ như vậy, https://cssreference.io

Giao diện trang chủ cssreference.io

Kéo chuột xuống hết phần màu mè, ngay phía sau dòng Collections sẽ có thanh tìm kiếm để tìm nhanh một thuộc tính. Hoặc bạn xem danh sách thuộc tính được xếp theo thứ tự ABC, click vào một thuộc tính bạn sẽ xem thuộc tính đó với ví dụ ngay kề bên để hiểu nó có tác dụng gì. Ví dụ:

Tra cứu thuộc tính line-height trong thanh tìm kiếm

Click vào gợi ý đề xuất để đến trang tham khảo về line-height, thấy như sau:

Thuộc tính kèm thông số được minh hoạ cụ thể, trực quan, dễ hiểu

Form dính với chân trang, giãn ra xem sao

Form để đặt trà sữa online hiện dính với chân trang, trông chưa thẩm mỹ cho lắm. Thêm một chút gì đó để FORM giãn ra, dễ coi hơn. Cũng thay đổi INPUT, SELECT bên trong FORM. Mã CSS và kết quả FORM:

FORM trông đã ổn hơn một chút.

Vài thứ vụn vặt khác để trang trông… diêm dúa hơn

Tìm trong file bai8.css đoạn đầu để thêm ảnh nền cho toàn trang web. Tui kiếm một cái ảnh nền dạng bong bóng bỏ vào thư mục images, và rule trông như sau:

Quay lại chỗ viết CSS cho table, ta thử thay đổi mã để cho việc khi xem bản, rà chuột đến dòng nào, nền dòng đó đổi màu. Đoạn rule giờ sẽ như này:

Hover table CSS

Việc biết các kỹ thuật CSS không đồng nghĩa với việc bạn có thể làm được trang web có tính thẩm mỹ cao nhưng cũng phần nào giúp bạn thực hiện được những trang trí thử nghiệm, thực hành nhiều hơn để càng ngày trang web trông đẹp mắt hơn.

Đến giờ này, bạn đã có thể làm được giao diện hiển thị được trên màn hình máy tính. Thử truy cập bằng điện thoại, bạn chỉ thấy được một phần của trang mà thôi.

Các bài tiếp theo sau, chúng ta sẽ tiếp tục chỉnh để cho giao diện có khả năng tuỳ biến. Từ ngữ dùng trong nghề thiết kế web là Responsive Web Design (viết tắt RWD). Nghĩa là khi truy cập bằng các thiết bị, trình duyệt có kích cỡ khác nhau, giao diện trang web sẽ được biến đồi theo cho phù hợp, hiển thị thông tin tốt, người dùng có thể duyệt dễ dàng.

Bài tập

  1. Bảng có cùng màu nền giữa các dòng sẽ khó đọc. Hiện nay người ta thích bảng kiểu một dòng màu màu đậm, dòng kế tiếp nhạt hơn và cứ luân phiên như vậy. Bạn hãy tra cứu zebra striped table CSS để có thể áp dụng vào TABLE.
  2. Khi click vào trường trong FORM nên có viền để người nhập thông tin dễ nhận diện. Bạn hãy thêm viền cho trường nhập liệu khi đặt trỏ chuột vào đó. Gợi ý: CSS input fields with color on focus để tìm ra ví dụ, áp dụng cho FORM.
  3. Sidebar bên phải màu hồng tím và màu chữ các món trên nó trông tương phản kỳ cục, rất khó đọc? Và các dòng chữ cũng khá sít nhau theo chiều đứng, cần giãn ra cho dễ đọc hơn. Bạn thử viết CSS để làm giải quyết. Gợi ý: tra cứu các thuộc tính: line-height, color, background-color, font-size.

Thảo luận: Bài 8: thêm chi tiết cho web trà sữa

Xem Bài 9: một số kỹ thuật CSS nâng cao

Bài 7: áp dụng CSS vào web trà sữa

Có thể nói rằng nếu chỉ có HTML, một trang web trông không khác gì những công trình xây thô, nhìn vào thấy còn nguyên gạch, vữa. Hoặc muốn dễ hình dung hơn, bạn tìm một hotgirl Trung Quốc để mặt mộc. Từ các bài trước, chúng ta đã làm một trang web về trà sữa chưa có chút nào CSS.

Bài hôm nay, chúng ta mở file bai5.html ra, Save As thành bai7.html để thực hành.

Tạo file CSS và viết vài rule

Tạo mới file bai7.css , save vào thư mục D:\xampp\htdocs\css (nếu chưa có thư mục css bạn phải tự tạo, đây là kiến thức tin học căn bản, KACBT mặc định bạn đã nắm biết).

Soạn nội dung file bai7.css như sau:

Hình 1. Nội dung file bai7.css

Luôn Save file lại trước khi làm gì hơn. Ta cũng nhớ lại lý thuyết đã học ở bài trước, giờ thì mở file bai7.html ra để sửa.

Hình 2. Dòng 5 chính là gắn CSS vào HTML

Save lại file và mở trình duyệt lên truy cập để xem thử hình hài trang web thế nào. Trông cũng vui mắt rồi:

Hình 3. Diện mạo trang web khi có chút CSS

Hoan hô bạn, giờ đây bạn đã thấy chút ánh sáng le lói cuối đường hầm. Trang web trông như được tạo ra ở thập niên ’90 của thế kỷ trước. Không sao, chúng ta đang ở mức học “Bảng cửu chương” trong quá trình học toán, rồi sẽ làm toán được.

Thêm một vài rule nữa, kèm chút giải thích

KACBT cũng nhại theo giới showbiz, tiết lộ cho bạn một… tin động trời: vừa rồi Kacbt đã gặp thảm hoạ về dữ liệu nên mất đã sạch tất cả những gì liên quan đến những bài học từ bữa giờ.

Vì thế cho nên, thực sự đoạn mã minh hoạ trong bài 7 này không còn, và KACBT cũng phải ngồi gõ lại từ bài 5.

Điều khôi hài xảy ra: nếu bạn chú ý quan sát, đoạn HTML hiện đang chưa đúng với ở bài 5. Ở bài 5 có một DIV bọc ngoài MAIN. Giờ phải sửa lại cho giống bài 5 đã rồi làm gì làm:

Bọc DIV có class là three-cols bên ngoài
Nhớ đóng thẻ DIV, nếu không gây lỗi valid

Cũng cần nói thêm rằng, bạn chỉ sửa mã như trên nếu bạn ngồi gõ mã ở bài này, còn nếu bạn đã Save as từ file bai5.html thì không cần phải làm gì thêm. Nếu đã làm rồi, hãy nhớ “undo” các bước, nếu không sẽ có 2 thẻ DIV bọc nhau chẳng để làm gì.

Mở file bai7.css lên, sửa rule cho header thành như sau:

Viết thêm một số dòng để trang trí HEADER

Chú ý: chữ .header (có dấu chấm phía trước header, và dính liền, không có khoảng cách)

Đọc thấy dòng ảnh nền ở trên, không cần phải nhắc bạn cũng phải biết rằng tìm một hình ảnh làm ảnh nền bỏ vào thư mục images để khi xem trang web hiện được ảnh này lên.

Có một phép mầu xảy ra khi bạn thử chỉnh hiển thị trang web bằng cách bấm Ctrl + dấu trừ để thu nhỏ trang web của bạn (hoặc màn hình của bạn rộng, hỗ trợ full HD trở lên), bạn sẽ chứng kiến được cái ảnh nền nó nhảy lặp lại một cái bên tay phải. Đó là mặc định của thuộc tính background-image, ta sẽ đi sâu thêm về sau.

Chỉ cần thêm vào sau dòng thuộc tính này, giờ đây rule cho HEADER trông như sau:

Không cho lặp lại ảnh nền bằng thuộc tính background-repeat có giá trị no-repeat

Nhớ bấm Ctrl + số không để trình duyệt bạn trở về xem trang web đúng 100% của nó. Nếu quên, tui có thể sẽ nhìn web của tui không đúng tỉ lệ thật của nó.

Bạn có thể tung hoành với CSS của bạn bằng cách thêm rule, bổ sung các thuộc tính cho rule đang có để làm thế nào cho trang web của bạn được đẹp hơn.

KACBT không “cầm tay chỉ việc” cho bạn những thứ đó, mà bạn phải tự động não, tự thực hành,… hòng tiến bộ, hiểu bài.

Chúng tôi chỉ có thể thử cung cấp vào rule, bạn có thể gõ lại vào file CSS để xem chuyện gì xảy ra, rồi có thể thay đổi để cảm thấy ưng ý hơn. Ví dụ, đoạn CSS sau:

Một vài khối rule CSS mà bạn có thể thử áp dụng

Một số thuộc tính được gọi là shorthand. Nghĩa là một thuộc tính shorthand cho phép thiết lập nhiều thuộc tính đồng thời thay vì phải viết rời từng thuộc tính. Áp dụng shorthand sẽ giúp viết CSS gọn gàng hơn.

Nhược điểm của shorthand là tui phải làm nhiều mới có thể nhớ đúng thứ tự các giá trị. Nếu không nhớ đúng, có thể kết quả sẽ khác với mong đợi.

Thuộc tính background là một thuộc tính dạng shorthand. Ta có ví dụ sau:

Viết rời từng thuộc tính

Đoạn nhiều thuộc tính như trên, gom lại thành 1 thuộc tính shorthand:

Thuộc tính background là thuộc tính shorthand

Bạn có thể tìm hiểu thêm về Shorthand properties trên trang của tổ chức Mozilla.

Một vài mẹo hay dân trong nghề phải biết

Dù bạn chỉ học làm web dưới dạng nghiệp dư amateur chơi cho vui, điều đó không ngăn cản KACBT và bạn trao đổi với nhau vài thứ của dân trong nghề, cũng dễ để áp dụng. Nào, bắt đầu ngay.

CSS Reset

Mặc định trình duyệt có một số định nghĩa ngầm, mặc định về CSS để khi mở một file HTML lên thì có thể hiển thị được nội dung, đọc được. Ví dụ: BODY sẽ có padding 8px, P có margin-top, margin-bottom là 16px.

Các trình duyệt web khác nhau lại không thống nhất nhau về giá trị mặc định. Điều này dẫn đến khi viết CSS, bạn đã kiểm tra tới lui thấy không có gì sai sót mà xem trang web lại không như mong đợi ở trình duyệt khác trình duyệt bạn yêu thích.

Bạn loay hoay đủ kiểu bạn vẫn bó tay. Các “đại ca” lâu năm trong nghề giải quyết vấn đề này bằng cách sử dụng cái gọi là CSS Reset (hoặc Reset CSS).

CSS Reset chính là một số rule CSS được viết sẵn. Mỗi khi bạn muốn viết CSS cứu copy các rule này vào đầu file CSS của bạn. Hoặc đặt các rule trong một file reset.css rồi nhúng ngay vào HTML của bạn trước khi nhúng các file CSS khác.

Nội dung CSS Reset như sau:

/***
    The new CSS reset - version 1.8.2 (last updated 23.12.2022)
    GitHub page: https://github.com/elad2412/the-new-css-reset
***/

/*
    Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
    - The "symbol *" part is to solve Firefox SVG sprite bug
 */
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
    all: unset;
    display: revert;
}

/* Preferred box-sizing value */
*,
*::before,
*::after {
    box-sizing: border-box;
}

/* Reapply the pointer cursor for anchor tags */
a, button {
    cursor: revert;
}

/* Remove list styles (bullets/numbers) */
ol, ul, menu {
    list-style: none;
}

/* For images to not be able to exceed their container */
img {
    max-inline-size: 100%;
    max-block-size: 100%;
}

/* removes spacing between cells in tables */
table {
    border-collapse: collapse;
}

/* Safari - solving issue when using user-select:none on the <body> text input doesn't working */
input, textarea {
    -webkit-user-select: auto;
}

/* revert the 'white-space' property for textarea elements on Safari */
textarea {
    white-space: revert;
}

/* minimum style to allow to style meter element */
meter {
    -webkit-appearance: revert;
    appearance: revert;
}

/* preformatted text - use only for this feature */
pre {
    all: revert;
}

/* reset default text opacity of input placeholder */
::placeholder {
    color: unset;
}

/* remove default dot (•) sign */
::marker {
    content: "";
}

/* fix the feature of 'hidden' attribute.
   display:revert; revert to element instead of attribute */
:where([hidden]) {
    display: none;
}

/* revert for bug in Chromium browsers
   - fix for the content editable attribute will work properly.
   - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/
:where([contenteditable]:not([contenteditable="false"])) {
    -moz-user-modify: read-write;
    -webkit-user-modify: read-write;
    overflow-wrap: break-word;
    -webkit-line-break: after-white-space;
    -webkit-user-select: auto;
}

/* apply back the draggable feature - exist only in Chromium and Safari */
:where([draggable="true"]) {
    -webkit-user-drag: element;
}

/* Revert Modal native behavior */
:where(dialog:modal) {
    all: revert;
}

Bạn cũng có thể sử dụng một mẫu CSS khác được gọi là normalize.css được xem là hiện đại hơn, có sự cải tiến hơn so với CSS Reset. Nội dung normalize.css như sau:

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */

/* Document
   ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/* Sections
   ========================================================================== */

/**
 * Remove the margin in all browsers.
 */

body {
  margin: 0;
}

/**
 * Render the `main` element consistently in IE.
 */

main {
  display: block;
}

/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/* Grouping content
   ========================================================================== */

/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */

hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/* Text-level semantics
   ========================================================================== */

/**
 * Remove the gray background on active links in IE 10.
 */

a {
  background-color: transparent;
}

/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */

abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}

/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */

b,
strong {
  font-weight: bolder;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/**
 * Add the correct font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/* Embedded content
   ========================================================================== */

/**
 * Remove the border on images inside links in IE 10.
 */

img {
  border-style: none;
}

/* Forms
   ========================================================================== */

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */

button,
input { /* 1 */
  overflow: visible;
}

/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */

button,
select { /* 1 */
  text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */

button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */

fieldset {
  padding: 0.35em 0.75em 0.625em;
}

/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */

legend {
  box-sizing: border-box; /* 1 */
  color: inherit; /* 2 */
  display: table; /* 1 */
  max-width: 100%; /* 1 */
  padding: 0; /* 3 */
  white-space: normal; /* 1 */
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */

progress {
  vertical-align: baseline;
}

/**
 * Remove the default vertical scrollbar in IE 10+.
 */

textarea {
  overflow: auto;
}

/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */

[type="checkbox"],
[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */

[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/* Interactive
   ========================================================================== */

/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */

details {
  display: block;
}

/*
 * Add the correct display in all browsers.
 */

summary {
  display: list-item;
}

/* Misc
   ========================================================================== */

/**
 * Add the correct display in IE 10+.
 */

template {
  display: none;
}

/**
 * Add the correct display in IE 10.
 */

[hidden] {
  display: none;
}

Chúng tôi không có lời bình nào về tốt/ xấu, hay/ dở của hai mẫu CSS kể trên mà bạn thử áp dụng vào chọn cái phù hợp với bản thân mình.

Hoặc, ở đẳng cấp cao hơn, bạn tự tay tạo ra một thứ cho riêng bạn. Đó chính là kết quả của việc học đã hiểu bài, áp dụng tốt và rồi nâng cao hơn một bước hơn so với số đông người học.

Nếu bạn để ý, ngay cả CSS Reset (hoặc Reset CSS) kể trên cũng đã là một bản cải tiến của cái nguyên ban đầu, phù hợp hơn với cách trình duyệt web hiện đại ngày nay.

Bản gốc Reset CSS của Eric A. Meyer cũng đã cải tiến 1 lần, như sau:

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}

Làm cho hình ảnh hiển thị trong khung hình tròn

Trong quá khứ, khi CSS hãy còn chưa mạnh mẽ như ngày nay, cách để có một hình tròn trên trang web đó là phải sử dụng trình xử lý ảnh để cắt gọn trước thành hình tròn rồi xuất thành ảnh GIF (thuở ban đầu), hoặc ảnh PNG có nền trong suốt.

Ngày nay, bạn dễ dàng tạo ra được ảnh trong khung tròn với chưa đến chục dòng CSS. Tui học thuộc lòng để áp dụng luôn.

Nếu hình ảnh của bạn vuông, hãy áp dụng đoạn HTML & CSS này.

Trong thực tế, hình ảnh đa số là hình chữ nhật chứ không phải hình vuông. Do đó, hãy sử dụng một trong hai lựa chọn sau đây tuỳ ảnh bạn là chữ nhật dọc (chiều rộng hẹp, nhỏ hơn chiều cao) hay chữ nhật ngang (chiều rộng > chiều cao).

Hình ảnh dọc thì áp dụng như này. Chú ý sửa kích thước cho phù hợp với mong muốn của bạn.

Trong khi đó, nếu hình ảnh bạn có xu hướng ngang, tức là chiều rộng lớn hơn chiều cao, hãy nhớ đoạn CSS bên dưới để áp dụng:

Hình ảnh ngang thì áp dụng CSS như này.

Canh giữa một khối trong một khối

Chúng tôi minh hoạ bằng DIV, bạn có thể dùng khối khác miễn khối đó có display là block.

Mẫu chốt của mẹo này là vùng khoanh đỏ trên hình

Như vậy, chúng ta kết thúc bài 7 này ở đây. Hẹn gặp bạn ở bài kế tiếp.

Bài tập thực hành

  1. Thay đổi FOOTER để trông bắt mắt hơn bằng cách thêm thông tin trong file HTML, thêm rule trong file CSS
  2. Thay đổi thanh lề trái, thanh lề phải của trang web
  3. Thêm nội dung cho phần MAIN để trang web trở nên hấp dẫn hơn
  4. Tham gia thảo luận Bài 7 ở diễn đàn.

Bài 8: thêm chi tiết cho web trà sữa


Một vài hình ảnh thực hành, thay đổi diện mạo

Trang chủ mới đầu, thôn nữ vùng quê chính hiệu:

Ảnh các ly trà sữa có vẻ nằm chưa chuẩn vào giữa trang, bị khuất mất ly bên phải. Ta có file CSS có nội dung như sau:

@import url("normalize.css");
.three-cols, .footer {
    width: 1330px;
    margin: auto;
    padding: 10px;
}
.header {
    background-image: url("../images/banner.jpg");
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
    height: 260px;
    width: 1330px;
    margin: auto;
    display: table;
}
.three-cols {
    /* background-color: lightblue; */
}
.left-nav, .main, .right-nav {
    float: left;
}
.left-nav {
    width: 240px;
    background-color: cyan;
}
.main {
    width: 850px;
    margin: auto;
    background-color: lightgray;
}
.tea-rows {
    width: 840px;
    margin: auto;
    margin-top: 1.5rem;
    display: flex;
    align-items: center;
}
figure {
    margin: auto;
    padding: auto;
}
figure > img {
    border: 1px solid darkgray;
    box-shadow: 3px 3px rgb(44, 43, 48);
}
figcaption {
    margin-top: 6px;
    color: blue;
}
.right-nav {
    width: 240px;
    background-color: magenta;
}
.footer {
    width: 100%;
    clear: both;
    background-color: lightyellow;
}
h1, h2 {
    text-align: center;
}

h1 {
    color: #ef510b;
    font-size: 4rem;
    display: table-cell;
    vertical-align: middle;
}

h2 {
    font-family: Arial, Helvetica, sans-serif;
    padding: 0.5em 1em;
    border-top: 1px solid #eeeeee;
    border-left: 1px solid #eeeeee;
    border-right: 1px solid gray;
    border-bottom: 1px solid gray;
    width: fit-content;
    margin: auto;
}
table {
    margin: auto;
    margin-top: 2rem;
    width: 80%;
    background-color: lightcoral;
    color: darkblue;
}
table > caption {
    font-size: 2rem;
    color: black;
}

form {
    width: 70%;
    margin: auto;
    margin-top: 2rem;
    background-color: bisque;
}
form > fieldset > div {
    margin: 1rem 1.2rem;
}
.footer {
    background-color: darkorchid;
    height: 100px;
    text-align: center;
}

Cho ra kết quả:

Giao diện web trà sữa.

Gửi email dùng server-side script với Gmail SMTP

Hiện nay nhiều nhà cung cấp web hosting không cho phép gửi email bằng hàm gửi mail mặc định bởi vì tình hình spam, hoặc gửi email được nhưng luôn rơi vào thư mục spam của người nhận. Đó là chưa kể có một sự thật thú vị: nếu cung cấp gửi email như vậy thì có còn mấy khách hàng đăng ký dịch vụ email hosting cơ chứ.

Do vậy, dân vọc Web sẽ nghĩ đến cách làm sao gửi được email. Cụ thể bài viết này sẽ hướng dẫn bạn cách làm sao để WordPress

Thực hiện theo hướng dẫn chính chủ từ Google

Chỉ cần đọc bài này và làm theo. Nếu làm được xem như xong. Chưa làm được bạn hãy đọc tiếp bên dưới.

Thực hiện từng bước một có hình minh hoạ

Truy cập vào trang bảo mật tài khoản Google. Lòi ra ngay màn hình như là:

Hình 1. Click 2, 3 như trên hình

Sau bước 3 nghĩa là đã bật được chức năng xác thực hai bước cho tài khoản Google.

Tại sao việc bật xác thực 2 bước này là quan trọng, buộc phải làm? Có 2 lý do cho vấn đề:

Thứ nhất: Google không còn cho phép dùng mật khẩu của tài khoản Google để xác thực việc gửi email thông qua một ứng dụng mà không có sự tương tác trực tiếp của con người.

Thứ hai: thật tai hại nếu lộ mật khẩu của tài khoản Google khi mà tài khoản đó đang được bạn dùng như một “chìa khoá vạn năng” mở cửa vào cánh cửa của mọi dịch vụ liên quan đến Google. Nếu lộ mật khẩu đó mà không kèm xác thực 2 bước, cuộc đời của bạn có thể rơi xuống bùn, thật chứ không đùa.

Vậy nên, sau khi kích hoạt được xác thực 2 bước rồi, ta mới là phần (4) App passwords như khoanh đỏ ở hình bên trên. Click mục đó, nó sẽ:

Hình 2. Màn hình cho phép tạo mật khẩu App

Nếu bạn đã từng tạo App password trước đây thì trong danh sách có liệt kê, còn không thì sẽ trống trơn. Giờ đây bạn quan tâm đến vùng như khoanh đỏ trên Hình 2.

Click chọn Select app xổ ra menu và chọc như hình dưới:

Hình 3. Đặt tên cho App mà bạn sẽ dùng

Nghe tên mật khẩu app, mật khẩu ứng dụng cực kỳ tối nghĩa với người Việt chúng ta, nhất là nếu bạn không phải dân công nghệ thông tin. Thực sự hiểu vầy cho dễ: Google xem các thứ kết nối tới dịch vụ của họ là một “ứng dụng” (phần mềm/ trình duyệt/ trang web/ phần mềm máy chủ).

Vậy nên, bạn cần đặt tên gì đó để sau này nhìn vào bạn biết/ gợi nhớ là cái mật khẩu này tạo ra để dùng làm gì, ở đâu. Không ai cấm bạn đặt trên nghe mỹ miều và vô nghĩa cả, nhưng đừng tự làm rối mình kiểu bạn bán cá nhưng có tên là Tôm.

Ngay khi gõ vài ký tự để đặt tên, bạn sẽ nhận thấy nút Generate chuyển trạng thái xanh cho phép click. Lúc này click sẽ sinh ra một cái gọi là App password, đây chính là kết quả chúng ta đang mong đợi.

Hình 4. Kết quả mật khẩu tạo ra.

Copy lại 16 ký tự chữ thường trong ô màu vàng/ cũng nên chụp ảnh màn hình lại để sử dụng về sau khi cần bởi vì ta không thể thấy được mật khẩu này thêm lần nào nữa. Bấm nút DONE để hoàn tất.

Dùng thông số cấu hình cho mã nguồn của bạn

Chúng tôi minh hoạ với code PHP, dùng thư viện nguồn mở có sẵn gọi là PHPMailer, nếu bạn sử dụng ngôn ngữ lập trình khác thì bạn chỉ cần sử dụng cú pháp của ngôn ngữ đó, lấy lại các thông số username và mật khẩu như trong hình.

Hình 5. Cấu hình SMTP Gmail dùng trong PHP.

Chú ý: thay cái mật khẩu ở hình trên với mật khẩu có được từ mục tương đương Hình 4 trên. Không có nghĩa là bạn lấy mật khẩu app của chúng tôi có email của bạn.

Đăng tại Chưa phân loại

Nhúng trình đọc file PDF của Google vào web

Bài này đơn giản là một hướng dẫn nhanh cho một học viên học Web. Anh ấy muốn cho khách truy cập trang đọc được những file PDF anh ấy tự làm hoặc sưu tầm được nhưng không muốn cho người dùng dễ dàng download về.

Sử dụng các thư viện để xử lý chuyên thì hoặc mất tiền hoặc quá khó cho người bắt đầu. Vì thế, chúng tôi hướng dẫn cách làm thông qua công cụ đọc file của Google.

Đưa file của bạn lên Google Drive

Truy cập vào trang drive chấm google chấm com để upload file PDF của bạn lên. Nhớ tạo một thư mục riêng trước khi upload file PDF vào, vì liên quan đến việc phân quyền, nên nếu để ở thư mục chung hoặc thư mục có nhiều file không muốn chia sẻ khác, bạn sẽ gặp rủi ro về bảo mật.

Khi file PDF đã được tải lên ngon lành, nhấp đúp lên file để xem, sẽ hiển thị file trong một hộp cho phép đọc file như một trình PDF reader hoặc PDF viewer. Lúc này, nhìn bên góc phải sẽ thấy:

Hình 1. Click dấu 3 chấm, click tiếp mục Share

Click vào vùng khoanh đỏ lần lượt từ trên xuống như trên hình, sẽ xuất hiện cửa sổ cho phép chỉnh thông số về chia sẻ, trông như này:

Thiết lập quyền chia sẻ trong Google Docs
Hình 2. Click vào biểu tượngbánh xe như trên hình.

Ở cửa sổ này, không thao tác gì trên cửa sổ ngoại trừ việc click vào biểu tượng hình bánh xe ở góc phải trên của cửa sổ như hình minh hoạ trên. Lúc ấy, một khung nhỏ khác hiện ra:

Thay đổi thiết lập chia sẻ file PDF
Hình 3. Click bỏ dấu tick ở mục thứ hai

Chỉ cần click bỏ chọn ở mục “Viewer and commenters can see…” đi. Quay lại cửa sổ Hình 2 click nút Copy link trước khi bấm nút Done. Lúc này ta có địa chỉ URL trong bộ nhớ, trông như sau:

Hình 4. Địa chỉ URL chia sẻ file PDF

Ta để ý cái dòng dài dài vô nghĩa này nó sẽ có cấu trúc nào đó, và ta sẽ thấy sau chữ d thường kèm dấu chém là một chuỗi “mật mã Da Vinci”, ta chọn đoạn này mãi cho đến dấu chém tới đứng trước chữ view. Như vùng chọn màu xanh là cây được minh hoạ:

Copy cái đoạn tô màu xanh lá cây.

Hiển nhiên, trong trường hợp file của bạn sẽ không giống hệt như cái đoạn minh hoạ ở trên rồi, nhưng nó vẫn nằm trong cấu trúc tương tự. Giờ thì bạn mở trình soạn thảo văn bản thô (Notepad nếu dùng Windows) hoặc code editor trên máy tính của bạn và chế biến nó trông như sau:

Mã embed PDF viewer của Google
Hình 5. Đoạn mã HTML cần dùng.

Vậy là bạn có đoạn HTML để có thể nhúng vào trang web của bạn rồi. Có thể làm ngay để xem thử.

Nếu bạn để ý kỹ, bạn không chỉ copy nguyên cái đoạn bôi màu xanh lá cây, mà bắt đầu luôn ngay từ đầu. Dễ dàng phải không nào.

Minh hoạ cho việc chúng ta vừa làm trông kết quả như sau:

Trong thực tế, nếu bạn thử nghiệm, người dùng mà không đăng nhập tài khoản Google (hoặc Gmail) của họ, họ sẽ không đọc được file PDF nhúng trên trang web của bạn đâu đấy.

Việc giải quyết cho người đọc không cần đăng nhập tài khoản Google của họ xin nhường lại cho bạn xử lý, đây là cách chúng tôi thường áp dụng để người đọc bài không nên làm theo như con vẹt mà cần phải có chút xoay xở để kỹ năng sử dụng máy tính, Internet ngày càng tốt hơn.

Tuy nhiên, chúng tôi gợi ý rằng bạn nên xem lại tuỳ chỉnh của bạn ở cái tương ứng với Hình 2 trong bài này.

Đăng tại Chưa phân loại

Gặp thảm hoạ cũng có cái hay

Bài viết đầu tiên cho chuyên mục này, lẽ ra gọi mục là blog cho dễ chịu, với tên “chém gió” hơi kinh dị ấy nhỉ? Kể về thảm hoạ với máy tính xảy ra cách đây mấy ngày như tự an ủi, cũng để thấy rằng chỉ một phút lơ mơ, xuống hố cả nút.

À, mà nhất là các bạn có thái độ phân biệt vùng miền, tui xin được nói trước là tui là một kẻ xét trên bình diện địa lý văn hoá, ngôn ngữ học, là người sử dụng một thứ tiếng trộn lẫn, nấu lẩu thập cẩm tả pí lù. Tui nhiều lúc sử dụng giọng điệu chua ngoa, gây khó chịu, lúc khác lại sử dụng phương ngữ của các “người anh em” trong cộng đồng 54 dân tộc… Những điều này là không chủ ý, nó là một thứ tui không lý giải được tại sao như vậy. Đen Vâu cũng không lý giải được sao anh ấy nói giọng Bắc nhưng khi hát (đọc Rap) lại giọng Nam.

Một buổi sáng đẹp trời

Đó là một ngày đẹp trời, trời Nha Trang mưa ơi là mưa, mỗi ngày có nhiều đợt mưa khác nhau, mưa rồi tạnh, tạnh rồi mưa.

Buổi sáng như mọi ngày, lên văn phòng đâu đó tầm 7:30. Việc đầu tiên: bật máy tính; việc tiếp theo: nấu nước pha cà phê.

Trong lúc chờ đợi cà phê vừa pha đủ nguội để làm một tợp như mọi ngày, hắn bật máy tính lên kiểm tra lại code kiếc hôm qua chạy ra sao. Bỗng cảm thấy ngạc nhiên đến bất ngờ khi hiện lỗi lên, trong khi tối hôm qua vẫn chạy tốt. Sau khi đọc thông báo lỗi đã được bật error_reporting(E_ALL); trong php.ini, xác định vấn đề là hỏng chức năng Memcached.

Hoá ra là thư viện liên kết động của một mô-đun PHP cách sao đó hôm qua chạy tốt, hôm nay bỗng không nạp được.

Có lẽ việc tương thích kém, vì thế, hắn lấy mã nguồn về để build lại luôn các thứ, rồi ghép vào, mất hơn hai giờ. Trong lúc gom các thứ, đàng nào cũng mất công build from source, sẵn tiện, nâng cấp lên phiên bản mới nhất của bộ 3 AMP của máy chủ LAMP luôn thể.

Thảm hoạ đã được gieo mầm

Vì cấu trúc thư mục dài dòng nên mỗi lần gõ lệnh phức tạp, vậy là làm vài cái soft link để rút gọi lại, đỡ vất vả phải gõ. Như vậy, có đến 3 cửa sổ Terminal trên Ubuntu được mở ra để gõ lệnh.

Sau một hồi gõ lệnh nọ lệnh kia, lúc này xong xuôi. Mới nghĩ dọn dẹp bớt cái mớ bùng nhùng chuẩn bị cho build trước đó cần gỡ bỏ. Vậy là gõ lệnh rm để dọn dẹp. Đã rất cẩn thận là thường chuyển vào thư mục mới gõ để xoá sạch bên trong, tránh nhầm ra bên ngoài. Thế quái nào trong các cửa sổ Terminal lại có cái cửa sổ đang đứng ở thư mục gốc của user mặc định mà dấu nhắc trông như đang ở thư mục cần dọn dẹp. Khi gõ lệnh xong, chuyển ngay qua cửa sổ khác để xem việc download một mã nguồn khác bằng wget tới đâu rồi, và dời qua bàn bên để lấy cà phê uống.

Khi quay lại máy tính, nhìn vào một cửa sổ Terminal tim tím, thấy download vẫn đang nửa chừng, chuyển qua cửa sổ gõ lệnh xoá vừa nãy vẫn chưa thấy dấu nhắc lệnh xuất hiện trở lại. Dựng tóc gáy, nhận thấy có gì đó sai sai. Lẽ nào xoá có vài thư mục mỗi thư mục chừng vài chục MB mà lâu đến như vậy. Vội vàng Ctrl + C để ngắt lệnh.

Nhìn lại mới thấy lần cuối partition dành cho /home dung lượng 367GB chiếm 97%, giờ chỉ còn chiếm 41%. Như vậy đi tong một lượng dữ liệu tính theo MB lớn hơn số còn lại.

Thiếu kinh nghiệm trong việc giữ nguyên hiện trường trên Linux

Lẽ ra lúc này dừng tất cả những gì đang chạy trên máy tính lại, để yên máy vẫn bật đó để ngồi sang máy khác tra cứu trên mạng Internet xem nên làm gì tiếp theo.

Lúc bấy giờ, hoảng loạn quá nên tui đã shutdown máy theo đúng chức năng của hệ điều hành. Cái này tưởng đâu giữ nguyên hiện trường nhưng thật tai hại làm sao.

Sau khi shutdown, lẽ ra là lấy ổ cứng mang sang máy khác để xử lý ngay còn được. Đàng này dại dột boot lại máy để chạy USB cứu hộ nhằm xử lý. Khởi động UEFI nó nạp nhanh quá, lóng ngóng bấm phím để chuyển sang ưu tiên khởi động USB không kịp, Ubuntu trên ổ cứng lại khởi động như bình thường.

Đây là lúc mà các phần mềm chạy nền đã ghi đè lên những file, thư mục đã bị xoá bởi lệnh rm gây ra thảm hoạ kia khiến cho việc phục hồi bất khả thi.

Bản sao lưu trong ổ cứng ngoài?

Cứ mỗi một tuần tui đều sao lưu một lần. Hài hước thay, trong tình huống này việc sao lưu lại chẳng có ích gì. Mọi thứ hay ho làm trong tuần vừa rồi đều bay sạch. Những tập tin, thư mục vừa tạo ra mới là cái cần vì source code được viết ròng rã mấy tháng gần đây được tinh chỉnh, di chuyển qua lại, có nhiều thay đổi lớn so với các tuần trước đây.

Vậy là bản sao lưu ở ổ cứng ngoài gần như chỉ để yên tâm rằng những thứ xưa cũ còn đó, chứ không ích gì cho công việc tuần này.

Tốn mớ tiền chứ không đùa

Gỡ ổ cứng qua gắn qua máy khác, chép lại một file image dạng RAW để vọc.

Chép nguyên ổ cứng ra thành Raw Image

Ổ cứng sau đó được gửi đi Sài Gòn để người ta phục hồi. Có hỏi qua điện thoại, chỗ phục hồi có nói rằng hồi giờ chủ yếu phục hồi với file dạng NTFS chứ còn ext4 trên hệ GPT là họ cũng chưa từng làm nhưng họ làm ở cấp thấp hơn, hy vọng vớt vát được phần nào.

Với bản RAW chép lại từ ổ cứng, tui đã mount lên thành ổ cứng ảo và dùng Live USB để boot máy lên thử cứu xem sao. Tình hình ngày hôm nay đang như hình:

Đang vớt vát lại chút file còn sót lại

Ba ngày đã trôi qua, bây giờ máy vẫn đang chạy như này:

Đang chép vài file phục hồi ra ổ cứng ngoài

Có cái hay là hay chỗ nào?

Chuyển sang ngồi máy mới dùng tạm, cũng phải tiếp tục công việc chứ không thì nhiều thứ không kịp bàn giao cho khách.

Lâu ngày không dùng máy tính chạy Windows, ngồi vào máy Windows cảm thấy lạ lẫm gì đâu. Gõ lệnh cứ phải cố nhớ lại các lệnh ngày xưa (lần cuối dùng Windows là năm 2011, nếu không kể việc thỉnh thoảng dùng Windows chỉ để in file PDF mà không đụng gì khác) mình từng biết là gì, kiểu như ls gì lại phải dir, rồi muốn xem file, bên Linux có cat, bên Windows bó tay, tra cứu PowerShell cũng muốn… vỡ mật.

Trong lúc đang vò đầu bứt tai vì công việc đình trệ, loay hoay với cái máy tính Windows cà khổ thì có lúc phải ngồi dựa ngửa ra mà thở… và có đứa bạn rủ tối hôm đó đi ăn xả xui.

Nghe đi ăn cảm thấy có lý thiệt đó, thật hay nữa là khác. Tối đến, đi ngay và luôn, vậy là tối 2 đứa đi ăn, lúc tạnh lúc mưa. Ăn xong lại mò về văn phòng xem thử liệu có thử tự cứu được quái gì không? Hỏng bét, mặc dùng là thư mục home đã nằm ở partition riêng nhưng vì đã khởi động máy lên, các ứng dụng chạy ngầm ghi be bét vào thư mục .config khiến cho mọi thứ loạn cả lên, không chắc cứu được gì nhiều.

Bài học lịch sử được rút ra

Tất nhiên là nếu gặp lại một lần nữa như hiện nay sẽ cứ để cho lệnh rm chạy cho xong luôn. Trong lúc đó không làm gì khác, cũng không shutdown máy luôn. Sau khi lệnh chạy xong sẽ:

  • Trích xuất journal ra
  • Dùng ext4magic để chép file bị xoá được phục hồi ra ổ cứng gắn ngoài

Nhưng bài học phụ trợ cho kinh nghiệm này đó là cuối mỗi ngày phải bỏ thời gian sao lưu “thành quả” của ngày hôm trước cho chắc ăn. Nhỡ có thảm hoạ xảy ra như lần này cũng không đau thương cho lắm.

Bài 6: lý thuyết về Cascading Style Sheets

Cascading Style Sheets (viết tắt: CSS) được định nghĩa là ngôn ngữ định kiểu phân tầng. CSS được dùng để trình bày tài liệu HTML hoặc XML. Nói cách khác, CSS giúp cho việc trình bày, trang trí, xếp đặt các đối tượng thành phần HTML để trang web sinh động, mỹ thuật.

Tại sao lại là phân tầng?

Cái chữ cascading này gây khó hiểu. Bạn cứ hiểu đơn giản CSS được tạo ra để tránh việc một tài liệu HTML có các thành phần được “sơn phết” tùy tiện, rối beng khiến cho việc chỉnh sửa trở nên khó khăn. Thuở ban đầu HTML đã lâm vào cảnh như vậy nên ai đó đã nghĩ ra CSS để giải quyết.

Bạn hình dung một rule trong CSS.

Giả sử bạn tên HTML. Bạn đang ở hữu một bộ đồ gồm quần, áo, mũ, găng tay, giày, phụ kiện, trang sức được chế tạo ra từ đầu dính liền các món thành một khối, không phải từng món rời vừa kể. Mỗi lần mặc bạn phải mở dây khóa khéo và chui vào bên trong rồi kéo lại một cách khó khăn vì vướng víu, nóng còn hơn quần áo bảo hộ Covid. Bạn cảm thấy thế nào với món thời trang ấy?

Hẳn nhiên là sau đó phải rã bộ đồ đó ra, tức “phân tầng” nó làm các loại/ nhóm: quần, áo, mũ, găng tay, giày, phụ kiện, trang sức. Khi tổ chức thành từng nhóm như vậy, đựng vào những tủ, ngăn tủ hoặc hộp riêng để có thể phối đồ thuận tiện khi cần lên đồ ra ngoài cho các sự kiện khác nhau.

Một element trong HTML dùng CSS để định kiểu dáng. Nói cách khác, bạn áp các rule (luật) được định nghĩa trong CSS vào các element trong HTML để thay đổi màu sắc, kiểu dáng, vị trí, màu nền, kích thước,… những thuộc tính của một khối trên trang.

Làm ngay một đoạn mã CSS xem sao

Lấy trang mẫu đã học ở bài đầu tiên ra, Save as lại thành bai6.html để thực hành.

Trong phần HEAD chỉnh sửa lại gần giống:

Đoạn này báo hiệu sẽ dùng CSS trong file styles.css

Tạo một file có nội dung:

Đặt trong file css/styles.css

Save file này với tên styles.css đặt ở thư mục htdocs/css

Đọc đoạn mã trên, bạn cảm thấy dễ hiểu phải không nào? Giải thích ngắn:

  • Những cái như border-style, border-color, color, width,… được gọi là thuộc tính (property hoặc properites nếu đề cập như là số nhiều).
  • Ngay sau thuộc tính là dấu hai chấm
  • Cuối cùng, sau dấu hai chấm là giá trị (value).

Cuối mỗi dòng thuộc tính: giá trị phải được kết thúc bằng dấu chấm phẩy (semicolon). Không được quên dấu chấm phẩy này, vì rất nhiều khi chỉ 1 thiếu sót bé xíu đó sẽ làm biến dạng mọi thứ, tui mất thời gian tìm lỗi, có khi còn gỡ không ra lỗi đến mức phải dẹp bỏ, làm file mới.

Tiếp tục, phần BODY của file bai6.html có nội dung:

Một DIV lorem ipsum
Khối DIV lorem ipsum

Mẹo: đừng ngồi mà gõ lorem ipsum bạn nhé, copy nó ở trang này.

Kết quả có được thật… không thể tin được 😀

Khối CSS màu xanh
Kết quả CSS đã có tác dụng vào khối DIV

Selector là cái quái quỉ gì?

Selector chính là khái niệm cốt lõi phải nắm trong CSS. Một element khi xuất hiện trong cây DOM sẽ được định danh bằng một cái tên nào đó người ta có thể hiểu được thay vì để trình duyệt tự định danh, cái tên này chính là selector.

Chúng ta xét đoạn mã HTML:

Đoạn mã HTML để giải thích về selector

Nếu sử dụng “ngôn ngữ trình duyệt” để diễn tả, trông như sau:

Selector chính là phần văn bản bắt đầu sau chữ body

Nếu ta sử dụng selector theo như trình duyệt gọi sẽ là quá dài dòng. Người làm web sẽ khóc thét vì độ phức tạp xen lẫn nhàm chán của việc copy & paste lại, sửa chữa số thứ tự, dễ gặp sai sót.

Vì vậy, người ta đã nghĩ ra một cách đặt tên lại cho các element đơn giản hơn thông qua tên thẻ (tag name), phối hợp các thuộc tính của element. Trong đó, hai thuộc tính thường dùng nhất là id, class.

Ta thử viết lại element chỉ logo thành:

Element hình ảnh có thuộc tính id, giá trị là logo

Nếu trong file styles.css mà ta viết theo cách của trình duyệt hiểu, nó sẽ:

Vậy, ta gọi #logo là selector

Như vậy, để trình duyệt khi đọc file HTML tìm đến đúng rule trong styles.css thì ta phải chỉ ra được element đang xem xét nằm ở đâu trong “rừng” các rule CSS. Lúc này, trình duyệt đơn giản là “nhìn vào” thuộc tính id, đọc được giá trị logo.

Tiếp theo, trình duyệt sẽ tìm đến rule bắt đầu bằng #logo trong file styles.css và lấy rule này để áp dụng định dạng cho element IMG mà ta đang xem xét.

Có một tình huống thú vị đó là ta có thể viết:

Selector dùng tag name (tên thẻ)

Nếu toàn bộ trang web hiện tại chỉ có đúng một element IMG như ví dụ này, hoặc bạn đang có ý định tất cả hình ảnh trên trang đều có viền nét liền, rộng 2 pixel, màu hồng cánh sen.

Những trang web ngày nay có hàng trăm, thậm chí hàng ngàn element. Nếu ta cứ luôn phải áp dụng theo kiểu đặt id như trên, thì xem ra cũng không mấy thú vị, bị quá tải vì quá nhiều id.

Do đó, luôn tồn tại cách khác, đó là người ta sử dụng thuộc tính class.

Vắn tắt lại cho dễ nhớ:

  • Nếu HTML không có id, class mà trong rule CSS ta dùng tên thẻ thì sẽ có hàng chục đến hàng trăm element sẽ được tác dụng bởi một rule. Cho nên, cách dùng tên thẻ chỉ áp dụng cho một số thẻ/ element chỉ xuất hiện một lần duy nhất trong một tài liệu HTML như BODY, HEADER, FOOTER.
  • Nếu HTML dùng id=”abcd” thì trong rule CSS ta sử dụng #abcd làm selector.
  • Nếu HTML dùng class=”efgh” thì trong rule CSS ta sử dụng .efgh làm selector.
  • Ngoài ra, selector nâng cao sẽ phối hợp giữa các thứ trên.

Giới thiệu một số thuộc tính, giá trị thường dùng

Có đến hơn 200 thuộc tính trong phiên bản CSS3. Ngay cả những người làm web kiếm cơm hàng ngày cũng không thể nhớ xuể. Bạn cần tra cứu khi dùng.

(*) Nếu tiếng Anh đủ tốt hoặc không ngại tra từ điển, bạn chỉ cần gõ Google như sau: background CSS properties, font css properties, color css properties… hoặc những thứ mà theo bạn chúng xuất hiện trong việc mô tả trang web.

Tiếng Anh chưa đủ tốt, thì dịch từ tiếng Việt sang tiếng Anh rồi làm như (*) bên trên. Bạn có hiểu ý KACBT muốn nói không? Ví dụ bạn gõ: cỡ chữ tiếng Anh là gì vào Google tìm kiếm, tra được từ font size, bạn nhập font size CSS vào Google là ra cái bạn cần đọc. Hoặc bạn muốn màu sắc đô

Dù sao, cũng duyệt xem qua danh sách > 200 thuộc tính đã kể trên.

Quy ước viết mã CSS đã được đề cập trước đây, bạn cứ theo đó.

Thuộc tính liên quan đến lề, khoảng đệm

Một khối được biểu diễn như sau:

2 khối: khối 1 nền vàng, khối 2 nền xanh lục

Thuộc tính liên quan đến văn bản

Một dòng chữ được viết bên trong một khối sẽ có các thuộc tính canh lề: trái (mặc định), phải (right), giữa (center), đều lề trái và phải (justify). Giờ đây, ta có minh hoạ:

File style.css có nội dung:

Nội dung file styles.css

File styles.css đặt trong thư mục css. Sau đó, nội dung file HTML ở phần HEAD có dòng kết nối đền file chứa nội dung CSS trông như này:

Dòng có số 7 có mục đích gắn CSS vào HTML

Hình minh hoạ trên chữ style.css sai, phải là styles.css

Nếu bạn vẫn chưa hình dung ra file HTML của mình trông thế nào, sau đây là toàn nội dung:

Toàn bộ nội dung HTML

Hình minh hoạ trên cũng sai, phải là styles.css, không style.css

Kết quả khi xem trên trình duyệt Web, trông không khác chút nào so với:

Kết quả của việc áp các rule (luật) CSS cho element

Chúng ta dễ dàng thấy rằng các luật CSS được viết trong file styles.css luôn có các dấu chấm đứng đầu: .hop-chua, .canh-giua, .canh-phai, .canh-deu-hai-le. Tuy nhiên, khi những định nghĩa này được áp dụng vào file HTML dưới dạng giá trị của thuộc tính class, ta không thấy dấu chấm xuất hiện nữa. Lúc này, chỉ còn là: class=”canh-giua”, class=”canh-phai”, class=”canh-deu-hai-le”

Ở đây, không có .canh-trai vì mặc định một đoạn văn trong khối được canh trái. Nhưng không cấm bạn thực hành việc tạo ra một rule có text-align: left.

Thuộc tính liên quan đến vị trí khối, kiểu hiển thị

Thành tố HTML (tức element) luôn có một giá trị hiển thị mặc định tuỳ thuộc element đó thuộc loại gì. Có hai giá trị hiển thị: block (khối) và inline (trong dòng).

Các element cấp khối (block-level elements): luôn bắt đầu một dòng mới và mặc định trình duyệt web sẽ thêm một khoảng hở nhỏ (margin) trước và sau khối.

Một block-level element luôn chiếm hết chiều rộng của khối cha mẹ. Có hai element thông dụng để tạo ra một khối văn bản đó là DIV, P. Ngoài 2 element thông dụng vừa kể, các element sau cũng thuộc nhóm block-level.

Các element có kiểu hiển thị mặc định là block

Trong khi đó, có vài element thông dụng như A, IMG, SPAN lại là inline-level element. Nói cách khác, chúng nằm trong dòng, không chiếm một “khoảng trời riêng” ở nơi chúng xuất hiện. Bạn hãy xem lại các bài trước, ở nơi có xuất hiện những element vừa liệt kê để thấy. Sau đây là những element mặc định có kiểu hiển thị là inline:

Các element có kiểu hiển thị mặc định là inline

Để rõ thêm, bạn sử dụng đoạn mã sau đây vào file HTML của bạn để thấy DIV rõ ràng là một block, còn SPAN là một inline:

DIV đại diện cho block, SPAN đại diện cho inline

Một khối bình thường xuất hiện trên trang HTML sẽ có position (vị trí) mặc định là static. Nghĩa là bạn không cần phải viết:

Mặc định trình duyệt hiểu position của một khối là static

Tương tự như vậy, với thuộc tính display, trình duyệt sẽ mặc định ngầm hiểu hoặc block hoặc inline tuỳ theo element thuộc nhóm block hoặc nhóm inline như đã đề cập ở trên. Trong một số trường hợp đặc biệt, bạn có thể thay thế thuộc tính display của một element từ inline sang block (trong thực tế, thường thấy với thẻ A, IMG) hoặc từ block sang inline (trong thực tế, thường thấy với thẻ LI).

Ngoài ra, thuộc tính display còn nhận các giá trị: inline-block, contents, flex, table,.. Bạn có thể tham khảo danh sách đầy đủ các giá trị của thuộc tính display.

Thuộc tính liên quan đến viền của khối

Viền khối có hai thuộc tính được sử dụng đó là borderoutline. Bạn sẽ thấy được sự khác nhau giữa border và outline:

Đoạn này trong file CSS style.css của bạn.

Trong khi đó, trong file HTML bạn sẽ có đoạn mã:

Đoạn này đặt trong file HTML

Sau khi save lại 2 file HTML và CSS, bạn có được kết quả:

Kết quả cuối cùng khi F5 refresh lại trang web

Bài tập:

  1. Đọc bài này bạn có phát hiện ra lỗi gì không? Gợi ý: lỗi liên quan đến file CSS, nếu bạn vẫn chỉ có một file bai6.html để thực hành, bạn có thể cảm thấy có đến 2 file CSS là styles.css và style.css. Chúng tôi cố tình viết lúc thì styles, lúc thì style để xem bạn xử lý việc này như thế nào. Hãy cho chúng tôi biết cách xử lý của bạn để chúng tôi nắm được bạn có hiểu bài hay không.
  2. Hãy thử thay đổi display mặc định của element: từ block sang inline hoặc inline-block hoặc ngược lại từ inline sang block rồi F5 nạp lại trang, quan sát, rút ra nhận xét.

Bài 7: áp dụng CSS vào web trà sữa


Chuyện gì nếu một trang web toàn HTML, không có CSS? Tui lượm được trên mạng thay lời giải thích.

Khi chỉ có HTML và khi đã thêm CSS.

Bài 5: trang web kết hợp hình, bảng biểu, biểu mẫu

Bài này đã có khá dồi dào những thẻ đã biết, chưa biết nhưng tra cứu dễ dàng, cách để biến thẻ (tag) thành element (phần tử/ thành phần) là như thế nào. Nào, giờ ta thử làm một trang web về trà sữa nghe cho có vẻ gì đó thơm ngon, hấp dẫn nhỉ?

Tham khảo các thẻ HTML để có thể tra cứu, sử dụng trong bài này.

Làm một giao diện truyền thống, đơn giản

Vì chúng ta tự học làm web, mang tính chất chơi là chính chứ không phải khắt khe tiêu chuẩn công nghiệp nên không có sẵn file PSD của bộ phận thiết kế chuyển qua để “cắt CSS”.

Thực hành cách viết mã HTML là chính, vì vậy, bạn chưa cần tốn thời gian công sức vào làm giao diện như các template thương mại.

Giao diện 1 trang web đơn giản, thập niên 1990s.

Phân tích về bố cục (layout) của trang, nhận thấy:

  1. Phần tiêu đề trang (header): lúc này còn làm đơn giản, chỉ có một dòng chữ Trà sữa Ánh Sao. Phần này thường hay cố định, trên website có nhiều trang thì các trang khác nhau đều có chung header.
  2. Phần tiếp theo có 3 cột (column): cột bên trái, bên phải có tên gọi chung là thanh lề (sidebar). Gọi riêng từng cột: cột có chữ Menu gọi là thanh lề trái (left sidebar), cột bên phải có 2 khung/ khối bên phải gọi là thanh lề phải (right sidebar). Hai khối bên trong cột bên phải gọi là khối (block) hoặc hộp (box). Cột chính giữa có hình thức uống được gọi là cột nội dung (main column hoặc content column).
  3. Phần cuối cùng của trang/ chân trang (footer): phần này thường có những thông tin gì, bạn tự quan sát các trang web khác để học tập. Ở đây chỉ giải thích gọn: khá giống với phần header, phần này thường giống nhau ở những trang web trong cùng một website.

Người ta cũng có thể phân tích theo cách có 4 phần: header, sidebar, main, footer, thay vì KACBT gom các cột thành một phần như trên.

Tới đây, bạn bỗng nhận thấy trong khi làm web, có rất nhiều từ vựng tiếng Anh cần phải biết, phải ghi nhớ, học thuộc. Một thành phần trên trang (page) có thể gọi bằng nhiều tên khác nhau đến mức ngay cả những người làm web có khi trao đổi với nhau cũng cảm thấy bối rối cho đến khi chỉ trực tiếp vào màn hình hoặc vẽ ra giấy.

Bạn hãy cố nhớ những từ, cụm từ, ngữ liệt kê trên. Chúng tôi sẽ thường xuyên lặp lại để giúp bạn dễ nhớ hơn, khi nhớ từ bạn mới tra cứu Google được, tìm được bài đọc chuyên sâu hơn.

Có nhiều bạn thường lên Facebook, các diễn đàn phàn nàn rằng anh ấy/ cô ấy đang gặp khúc mắc một vấn đề nhưng không biết từ khóa để tra cứu, ai đó giúp giùm đi. Nguyên nhân của việc này là vì họ… lướt đi quá nhanh, học mọi cái theo kiểu “cưỡi máy bay ngắm hoa” khiến trí não chưa kịp ghi nhớ một số thứ cần nhớ, khi cần đến đành bó tay, đi hỏi đợi người ta trả lời. Hóa ra, nhanh thành chậm vậy, thật là “dục tốc bất đạt”.

Trang web có đội dài khác với trang giấy, nó không chỉ gói gọn trong vùng một màn hình mà có thể cuộn trang. Phần giao diện mẫu trên chỉ thể hiện phần nạp trong khung màn hình ban đầu.

Bài này sẽ có thêm những phần không có trên giao diện: bảng liệt kê các món theo mùa, form đặt món ở phần MAIN.

Chuyển giao diện trên thành các tag, element

Trước đây, thời KACBT mới học làm web, thời đó người ta cứ dùng DIV cho mọi khối trên trang web. Ngày nay, ai làm vậy chứng tỏ rằng hoặc ẩu, hoặc bảo thủ hoặc làm biếng cập nhật kiến thức.

Ngay lúc này, bạn phải xác định rằng áp dụng ngay các thẻ Semantic Web vào thực tế. Tránh dùng thẻ một cách bản năng, theo thói quen vì không tốt về Accessibility.

Các máy tìm tin đánh giá thấp các trang web dùng thẻ vô tội vạ. Đó là nguyên nhân nhiều người cứ thường xuyên than vãn vì sao trang web họ không thể tìm thấy trên Google, làm SEO các kiểu, tốn mớ tiền nhưng vẫn chìm nghỉm tận đâu.

Bạn sẽ tự gõ lại mã HTML, trong phần BODY, file bai5.html của bạn, theo hình lần lượt:

Phần Header dùng thẻ HEADER, bên trong có tiêu đề H1

Phần có 3 cột sẽ được bọc trong 1 DIV:

Một DIV bọc 2 thẻ ASIDE, 1 thẻ MAIN

Tự phát triển mã cho đầy đủ. Cứ lần lượt theo thứ tự giao diện như đọc sách: từ trên xuống dưới, từ trái qua phải. Hiển nhiên, mã HTML bạn viết trong file HTML sẽ chỉ có từ trên xuống dưới, chứ không thể làm thanh các khối giống như trên hình.

Khi xem trang, nếu ở bài này mà bạn vẫn chưa hiểu rằng tại sao nó vẫn chưa đẹp. Chữ, đoạn văn, hình cứ hàng dọc từ trên xuống dưới, không giống tí gì giao diện trên. Bạn thử quay về Bài 1 để nhớ lại chúng tôi đã giải thích, từ từ rồi trang web sẽ phong phú, đẹp đẽ lên.

Chi tiết hóa thêm từng khối một bên trong DIV 3 cột

Nhắc lại cho nhớ: một thẻ (tag) khi được viết hoàn chỉnh có thẻ mở, thẻ đóng, kèm các attribute thì được gọi là một thành phần/ phần tử (element). Trong DIV chứa 3 element:

ASIDE đầu tiên:

Thẻ ASIDE đầu tiên, bên trái
ASIDE có chứa 2 phần tử con là H2, UL

Thuộc tính class=”left-nav” là để chuẩn bị cho những bài sau khi ta học đến CSS.

Thẻ UL khởi tạo danh sách không thứ tự, mỗi thẻ LI là mỗi mục trong danh sách. Trong thẻ LI ta có dùng thẻ A mục đích để tạo liên kết, khi click chuột vào mục sẽ ra chi tiết về món.

Hiện nay chưa có trang hoặc URL nào để thẻ A trỏ đến, người ta dùng href=”#” tạm, sau này điền URL thay vào dấu #

Bóng đèn, mẹo hay Nếu bạn muốn tạo danh sách có thứ tự, thay UL bằng OL

Ngay sau thẻ đóng ASIDE, tiếp tục đến MAIN, đây là một thẻ tương đương DIV nhưng ám chỉ rằng nơi đây đích thị là nội dung chính của trang web.

MAIN có đoạn mã gần như sau:

Thẻ main HTML
Mỗi dòng có 3 hình ảnh thức uống

Vùng khoanh màu đỏ trên hình là 1 đoạn mã đại diện, KACBT không viết thay bạn mọi thứ. Bạn tự tạo thêm 2 bản giống vậy ngay bên dưới, sửa giá trị thuộc tính cho phù hợp để cuối cùng có tổng cộng 3 dòng, mỗi dòng 3 hình, tức 9 hình đầy đủ như minh họa ở hình layout.

Hình 1 đến hình 9 (các file cup1.png, cup2.png,… ở thẻ IMG) bạn tự tìm kiếm hình ảnh trên Internet. Tải ảnh về, chỉnh kích cỡ cho các ảnh để mỗi ảnh không rộng quá 320 pixel. Lý do: ảnh rộng khiến cho màn hình desktop không chứa nổi 3 ảnh theo chiều ngang, mobile bị tràn lề.

Gợi ý từ khóa tìm kiếm: bubble tea images

Tui vừa học thêm được 2 thẻ mới bữa giờ chưa biết:

  1. Thẻ FIGURE để đóng khung hình lại giống như tranh treo tường ở nhà bạn vậy. Bên trong sẽ có tranh vẽ trên nền chất liệu vải hoặc giấy. Hoặc dễ hình dung hơn, bức hình minh họa trong sách, báo. Bản thân FIGURE chỉ là khung tranh, bạn phải có thẻ IMG bên trong, nếu cần có lời ghi chú cho hình ảnh thì dùng thêm thẻ FIGCAPTION, nếu không ghi chú gì thì khỏi có FIGCAPTION.
  2. Thẻ FIGCAPTION để có dòng ghi chú cho hình ảnh bởi thẻ IMG đang là anh chị em cùng cấp với FIGCAPTION trong cùng cấp cha mẹ FIGURE.

Quái, tại sao lại đẻ thêm ra FIGURE, FIGCAPTION chi cho rắc rối sự đời? Chỉ cần IMG với thuộc tính alt, title là đủ để dàn hình cho đẹp rồi?

Một lần nữa, KACBT muốn nhấn mạnh: bất cứ thẻ HTML nào được tạo ra cũng có mục đích của nó, thẻ FIGURE giúp bổ sung tính ngữ nghĩa cho thẻ IMG, nó cũng không chỉ dùng để chứa IMG bên trong, bạn có thể tự Google tham khảo thêm.

Việc tham khảo danh sách các thẻ, áp dụng trong khi làm web chính là sự sáng tạo của người làm web. Một kết quả trình bày lên trên trang web có nhiều cách làm khác nhau. Đó chính là sự thú vị của thế giới HTML, web.

TABLE thuộc về (con của) MAIN sẽ là một bảng đơn giản. Kết quả như hình:

Thẻ table có THEAD, TBODY, CAPTION.
Lần này TABLE có thêm CAPTION

Bạn nhìn hình trên, suy nghĩ và thử viết mã HTML, sau đó đối chiếu với mã:

Bảng biểu có dùng caption
Đoạn mã TABLE có CAPTION

Giờ đây, khi khách hàng nhìn qua vài thứ hấp dẫn trên trang web của bạn, họ muốn đặt món ngay. Bạn hãy đáp ứng nhu cầu này ngay tức thì bằng cách dùng form, gợi ý sau:

Form đặt món ăn vặt, trà sữa online
FORM đặt món online

Mô tả cách làm một cách thô sơ để bạn thử làm: đầu tiên tạo thẻ FORM. Bên trong FORM tạo ngay FIELDSET. Bên trong FIELDSET tạo ngay LEGEND có dòng text Form đặt món. Đóng LEGEND ngay.

Vẫn còn đang trong FIELDSET làm tiếp các LABEL, INPUT (có các type=”text”), SELECT (có tag con là OPTION), cuối cùng là nút Đặt món có thể chọn INPUT hoặc BUTTON đều được, nhưng nhớ type=”submit thì nút bấm mới có tác dụng gửi thông tin.

Đối chiếu mã bạn tự viết với mã dưới:

Mã HTML của FORM hoàn chỉnh

Đoạn mã trên do KACBT kèm một ngươi trực tiếp làm, bạn có phát hiện ra sai sót vì thích nhanh nên làm kiểu copy & paste khi chưa đủ độ tinh thông?

Bạn hãy sửa lại giúp ở thẻ SELECT giờ giao hàng, name lúc này không thể là item được, phải đổi thành time hoặc gì đó khác vì nó trùng với gọi món trên, khi gửi FORM sẽ mất thông tin.

Thuộc tính maxlength=”số nguyên” quy định độ dài tính theo byte (theo chuẩn UTF-16) mà INPUT chấp nhận. Để tránh những người duyệt web ác ý (nhưng không đủ trình độ để dùng công cụ khác trình duyệt web) nhập dữ liệu rác, dài lê thê lên server, bạn nên đặt maxlength để trình duyệt loại bỏ những thứ dài dòng.

Hôm trước, chúng ta có biết thuộc tính size của INPUT. Size là để chỉ số ký tự có thể hiện lên màn hình, hiểu đơn giản đó là độ rộng khi xem INPUT trên màn hình. Còn maxlength là sức chứa dữ liệu của INPUT, tính theo byte. Trong thực tế, dòng chữ dài vượt khỏi phạm vi màn hình là hết sức bình thường.

Biểu tượng cảnh báo Thuộc tính id, name không được chứa giá trị trùng nhau (trừ name sử dụng cho RADIO). Nghĩa là nếu đoạn mã bên trên đã có id=”gia-tri-a” thì đoạn dưới không được id=”gia-tri-a” nữa, mà phải id=”gia-tri-khac”. Với name, tương tự như id. Dễ hiểu hơn, trong 1 danh sách không được có 2 thành viên trùng số điện thoại di động, trùng số CMND.

ASIDE thứ 2 (sau này sẽ thành cột bên phải, còn giờ nó cứ nối đuôi MAIN mà thôi)

ASIDE lề phải có 2 khối DIV con

Gần giống với ASIDE đầu tiên đã đề cập trước, chỉ khác rằng bây giờ được chia làm 2 khối DIV. Khối đầu tiên là để dành cho Ưu đãi, khối thứ hai dành cho Giải trí.

À há, bạn có kịp phát hiện ra đoạn mã trên thiếu gì đó? Hãy bổ sung H2 làm tiêu đề cho mỗi khối nhé.

Đến đây, chúng ta đã hoàn thành phần phức tạp nhất của trang web rồi. Nếu tóm tắt mã gọn lại sẽ trông như này:

Hoàn chỉnh phần 3 cột
Mã HTML được lược bớt để xem tổng quát

Phần chân trang (footer)

Phần này đơn giản, chẳng có gì đáng nói chỉ có điều là thay vì dùng thẻ P hoặc H1 đến H6 như thường dùng, kết hợp một thẻ mang tính ngữ nghĩa ADDRESS.

Phần footer trang web
FOOTER quá đơn giản.

Cũng để ý rằng thuộc tính href của thẻ A như trên là để người truy cập có thể click vào số điện thoại sẽ mở chức năng gọi điện ra, thuận tiện gọi ngay mà không phải ghi nhớ rồi nhập số gọi thủ công.

Tạm hoàn tất việc “viết mã thô” cho trang HTML của chúng ta. Mở trình duyệt lên, bạn sẽ thấy tất cả xếp hàng dọc dài, nếu ảnh không xuất hiện, cần kiểm tra lại đường dẫn để sửa.

Giải thích việc xuất hiện thuộc tính class

Khi học về CSS ta sẽ hiểu rõ hơn về thuộc tính class. Hãy cứ gọi là class luôn nhé, vì KACBT cảm thấy chữ dùng chữ “lớp” có gì đó tối nghĩa, từ khác là từ nào trong tiếng Việt vẫn chưa nghĩ ra.

Thuộc tính này sẽ có giá trị là một hoặc nhiều tên class (classname) sẽ dùng làm selector khi viết các rule bên CSS.

Để dễ hình dung, bạn đang đứng trần truồng, và bốc từng món đồ mặc vào người, những cái đó nếu viết theo ngôn ngữ HTML trông như sau:

Giải thích về class phần 1
Giá trị của class tự đặt, miễn đúng quy cách tên gọi trong HTML

Theo như hình trên, người ta nói thẻ NGƯỜI có 1 classnameáo. Tương tự, ta có thể có thêm các classname khác, chúng cách nhau bằng 1 khoảng trắng.

Giải thích về class phần 2
Classname áo, quần cách nhau bằng khoảng trắng

Khi class chứa nhiều giá trị, gọi là Multiple Classes.

Chìa khóa ghi nhớ Classname phân biệt chữ HOA, chữ thường nên phải hết sức cẩn thận. class=”my” khác class=”My”

Minh họa một classname phức tạp.
Multiple classes

Kết thúc bài này: khi viết CSS thì classname sẽ có dấu chấm đứng kề trước nó. Ví dụ ở đây ta có class=”zone-heading” thì khi viết CSS sẽ có .zone-heading

Bài tập thực hành mở rộng vấn đề

Phần MAIN hãy còn rất sơ khai với 9 cái hình đứng chơi vơi mà thôi. Bạn hãy làm cho nó thêm nhiều thứ cho ra một trang dài dài. Ví dụ:

  1. Dùng TABLE tạo một bảng các món uống dành cho mùa hiện tại, ngay trước phần form đặt món.
  2. Thêm một vài hình ảnh chụp quán ngay sau phần đặt món cho đẹp.
  3. Làm phần “Nhận xét của khách hàng”, đơn giản là làm một DIV, bên trong có chứa 1 IMG để avatar nhỏ của khách hàng, 1 P để ghi lời nhận xét.
  4. Tự thêm vào phần MAIN hoặc ASIDE những gì bạn cảm thấy cần thêm để khách hàng dễ truy cập hơn khi ghé vào trang chủ.

Đừng quên tham gia thảo luận bài này.

Bài kế tiếp Bài 6: lý thuyết về Cascading Style Sheets.

Bài 4: trang web có biểu mẫu

Các đơn từ làm sẵn trên giấy có để chỗ trống để điền được gọi là biểu mẫu (form). Trong tài liệu HTML cũng thường hay dùng biểu mẫu để nhận thông tin từ người dùng.

Tạo một biểu mẫu đơn giản

Dùng thẻ FORM để khởi tạo một biểu mẫu. Bên trong biểu mẫu này sẽ dùng các thẻ LABEL để ghi lời nhắc cho mục cần điền, và thẻ INPUT chính là chỗ để điền thông tin.

Hình 1. Form đơn giản với 3 trường INPUT

Form ở trên chưa có nút gửi, nên chỉ có thể điền thông tin xong, ngắm nhìn mà không làm gì được thêm. Chúng ta sẽ lần lượt làm nó hoàn thiện hơn.

Các thuộc tính của FORM

Form thường có 2 thuộc tính đi kèm:

  • Thuộc tính action thường kèm giá trị là một địa chỉ URL để thông tin form gửi đến địa chỉ đó xử lý. Thông thường, giá trị là một file cùng domain với file HTML chứa form. Ví dụ: action=”save.php”. Người làm web tĩnh không cần biết về việc xử lý dữ liệu thế nào. Việc đó dành cho người lập trình xử lý ở phía server (server-side hoặc back-end). Giá trị action cũng có thể là một URL trỏ tới một dịch vụ chuyên xử lý form bên ngoài, nhưng gần đây sẽ hiện cảnh báo đến người dùng khi gửi form.
  • Thuộc tính method, nếu bản chất việc gửi một mẩu thông tin ngắn lên để yêu cầu truy vấn về một lượng thông tin lớn hơn từ web server (ví dụ như form tìm kiếm Google, tìm kiếm/ lọc thông tin ở các trang web báo chí, thương mại điện tử) thì ta dùng method=”get” . Nếu ta gửi nhiều trường thông tin, có upload file, ta dùng method=”post”

Từ nay trở đi, mỗi khi tạo mới 1 biểu mẫu, hãy nhanh tay nhập nội dung sau:

Khi tạo FORM chưa xác định method, không có upload file

Nếu FORM có upload file, dùng mẫu sau:

FORM có trường input kiểu file

Các trường INPUT trong FORM

Hầu hết các thẻ đều có thể đặt bên trong một FORM. Các thẻ như DIV, P, SPAN,… này nọ để hiển thị các dòng chữ, các hướng dẫn giúp cho việc điền form được dễ dàng hơn. Tuy nhiên, có những thẻ sau đây bạn cần biết vì đây chính là nơi để thực sự nhận thông tin/ dữ liệu người dùng nhập vào hoặc thẻ đó chỉ nên dùng bên trong form để trang trí, định dạng form.

Thẻ INPUT: thẻ này là thẻ dùng chỉnh để tạo hộp chữ nhật (textbox) cho phép nhập dữ liệu. Thẻ INPUT thường có các thuộc tính id, class, title (là những thuộc tính không đặc trưng riêng cho INPUT), và các thuộc tính (attribute):

type: chấp nhận các giá trị text, email, radio, number, tel, submit, button, hidden…. Trong đó, giá trị text chiếm phần lớn. Ví dụ: <input type=”text” name=”area”>. Một khi type=”hidden” đây là một điều khá đặc biệt, INPUT sẽ không có biểu hiện gì hiện ra trên màn hình nhưng nó vẫn có thể chấp nhận value=”giá trị”. Điều này thật quý giá khi người làm web cần gửi những thông tin để server xử lý, mà những thông tin này người sử dụng bình thường không cần quan tâm, không cần nhìn thấy. Chúng ta sẽ rõ điều này khi học căn bản về lập trình server-side (còn gọi là back-end).

name: chấp nhận giá trị là một tên hợp lệ (tra cứu ID and NAME tokens), bắt đầu luôn bằng ký tự. Nếu FORM được sử dụng đúng, không dùng kỹ thuật AJAX để gửi form, các trường INPUT luôn có name để việc gửi thông tin lên server giúp cho bên lập trình có thể lấy được thông tin. Giá trị của name nên đặt trùng với giá trị của id (nếu id không chứa dấu gạch ngang) để dễ đọc mã, gỡ rối. Ví dụ: <input id=”family” type=”text” name=”family”>

value: chấp nhận giá trị rỗng hoặc giá trị mặc định tạo trước hoặc được nạp từ server với những input có giá trị định sẵn ban đầu. Khi INPUT không có value đồng nghĩa với value=”” (có giá trị rỗng). Ví dụ: <input id=”phuong-tien” type=”text” name=”phuong_tien” value=”Xe máy”>. Giá trị của value có thể là kiểu số, kiểu chuỗi, tiếng Việt/ Anh đều được tùy theo type là gì, nếu type là email thì phải đúng cú pháp của email, nếu type là number thì số nguyên âm, 0, số nguyên dương.

size: chấp nhận giá trị là một số nguyên, mỗi số xấp xỉ với độ rộng của một ký tự, chỉ định độ rộng của hộp chữ nhật, ngày nay ít dùng thuộc tính này vì sẽ định dạng bằng CSS cho độ chính xác đến từng pixel cao hơn. Ví dụ: <input type=”number” name=”year” size=”8″>

required: đây là thuộc tính không có giá trị, bản thân của nó chính là giá trị. Những trường INPUT nào bạn muốn rằng người dùng buộc phải điền hoặc chọn thông tin mà không được bỏ trống/ bỏ qua thì bạn chỉ cần có thuộc tính này, nghĩa là “bắt buộc phải có” (hoặc được yêu cầu). Ví dụ, để liên lạc được thì phải có số điện thoại: <input type=”tel” name=”phone” required> để người dùng buộc phải điền số điện thoại.

placeholder: trước đây, khi HTML phiên bản 4, người ta phải dùng giá trị tạm, title các kiểu để gợi ý người dùng biết nhập thông tin. Ngày nay, placeholder giúp bạn điền gợi ý. Ví dụ: <input type=”text” name=”hoten” placeholder=”Nguyễn Văn Thành”>

Thẻ INPUT là một trong những thẻ thuộc loại rắc rối, phức tạp nhất trong HTML. Cần phải thực tập nhiều để quen, làm chủ được nó.

Chìa khóa ghi nhớ Luôn có thuộc tính name cho INPUT. Ngay khi tạo thẻ INPUT hãy name=”ten” ngay để không sai sót.

Một FORM hơi phức tạp

Giờ đây, chúng ta có một FORM khác, phức tạp hơn:

Mã HTML của một FORM có chút phức tạp

Kết quả tạo ra biểu mẫu form từ đoạn mã trên:

Bấm nút Gửi đăng ký ở trang web từ mã do bạn viết xem sao

Vài dòng giải thích để bạn hiểu thêm về đoạn HTML khá dài trên:

  • Thẻ INPUT khi có type=”radio” hiện lên nút tròn để chọn.
  • Thẻ LABEL có thể đứng trước hoặc đứng sau INPUT đều được tùy theo bố trí sao đó cho đẹp. Với các INPUT có type=”radio”, type=”checkbox”, đặt LABEL phía sau sẽ phù hợp hơn, còn lại các INPUT khác, LABEL phía trước.
  • Khi INPUT có type=”radio” thì phải có ít nhất 2 cái trở lên (khi click chỉ chọn 1 mà thôi) trong cùng FORM thì mới có sự chọn lựa. Lúc này name của các radio này phải có giá trị trùng nhau.
  • Khi INPUT có type=”checkbox” sẽ hiện lên hộp vuông, và có thể click chọn nhiều mục khác nhau, các name không đặt cùng tên như radio.
  • Nên viết đầy đủ là <label for=”id-của-input”>Gợi ý cho INPUT</label> : tại sao nên viết kiểu này mà không dùng các thẻ như P, SPAN? Lý do: 1 web được làm tốt cần hỗ trợ “Web accessibility” cho phép những người có khuyến tật về mắt sử dụng trình duyệt đọc hiểu được mục đang xem là gì. Đây là một vấn đề nhân văn mà những người sáng chế ra Web ngay từ đầu đã khuyến khích. Ta nhớ đặt <input id=”id-của-input” type=”text”> để LABEL trỏ đúng, khớp với INPUT này.
  • Viết <label>Mục input</label> là cách làm ẩu, không chuẩn. Ta dùng cách <label for=”id-của-input”>Mục input</label> hoặc ta đặt INPUT bên trong LABEL như sau: <label>Họ và tên <input type=”text” name=”hoten” size=”20″></label>

Hãy tự sửa code sai chúng ta vừa tạo ra

Khi học đến đây, bạn chợt phát hiện ra rằng KACBT dạy bậy bạ. Nhất là ở Hình 1 ở đầu bài đã dắt bạn đi sai bậy bạ mất tiêu rồi. Thực sự, việc sai sót rất bình thường, trong quá trình học người học cần phải tham khảo vài nguồn khác nhau, thực hành nhiều, có lúc phải “cãi lại thầy” mới mong tiến bộ.

Nếu bạn đọc bài và làm theo, sai đúng thế nào cũng mặc kệ, bạn sẽ rất khó tiến bộ. Đó là điều KACBT muốn truyền tải qua bài này.

Bóng đèn, mẹo hay Tham khảo danh sách đầy đủ các type của INPUT.

Tự học thêm khi FORM có thêm các trường món khác

Hãy tra cứu cách sử dụng FIELDSET, LEGEND, INPUT có type=”file”, BUTTON, TEXTAREA cho FORM của bạn. Tạo ra ít nhất 5 FORM khác nhau, mỗi FORM có độ 5-7 trường để thực hành.

Thảo luận ở diễn đàn dành cho bài này.