Jumat, 28 Februari 2014

Mengambil URL Gambar Pertama dari Posting

Versi PHP

function get_first_image_url($data, $default_url = null) {

/**
* Matched with ...
* ----------------
*
* [1]. `![alt text](IMAGE URL)`
* [2]. `![alt text](IMAGE URL "optional title")`
*
* ... and the single-quoted version of them
*
*/
if(preg_match_all('#\!\[.*?\]\(([^\s]+?)( +([\'"]).*?\3)?\)#', $data, $matches)) {
return $matches[1][0];
}

/**
* Matched with ...
* ----------------
*
* [1]. `<img src="IMAGE URL">`
* [2]. `<img foo="bar" src="IMAGE URL">`
* [3]. `<img src="IMAGE URL" foo="bar">`
* [4]. `<img src="IMAGE URL"/>`
* [5]. `<img foo="bar" src="IMAGE URL"/>`
* [6]. `<img src="IMAGE URL" foo="bar"/>`
* [7]. `<img src="IMAGE URL" />`
* [8]. `<img foo="bar" src="IMAGE URL" />`
* [9]. `<img src="IMAGE URL" foo="bar" />`
*
* ... and the uppercased version of them, and the single-quoted version of them
*
*/
if(preg_match_all('#<img .*?src=([\'"])([^\'"]+?)\1.*? *\/?>#i', $data, $matches)) {
return $matches[2][0];
}

return $default_url; // Default image URL if nothing matched
}

Penggunaan

<img src="<?php echo get_first_image_url($page['content'], 'img/no-image.png'); ?>">

$page['content'] cuma contoh. Anda harus mengambilnya dari konten posting Anda sesuai dengan API pada CMS yang Anda pakai.

Versi JavaScript

function getFirstImageURL(data, noImage) {

/**
* Matched with ...
* ----------------
*
* [1]. `![alt text](IMAGE URL)`
* [2]. `![alt text](IMAGE URL "optional title")`
*
* ... and the single-quoted version of them
*
*/
var matches = /\!\[.*?\]\(([^\s]+?)( +[\'"].*?[\'"])?\)/.exec(data);
return matches ? matches[1] : noImage;

/**
* Matched with ...
* ----------------
*
* [1]. `<img src="IMAGE URL">`
* [2]. `<img foo="bar" src="IMAGE URL">`
* [3]. `<img src="IMAGE URL" foo="bar">`
* [4]. `<img src="IMAGE URL"/>`
* [5]. `<img foo="bar" src="IMAGE URL"/>`
* [6]. `<img src="IMAGE URL" foo="bar"/>`
* [7]. `<img src="IMAGE URL" />`
* [8]. `<img foo="bar" src="IMAGE URL" />`
* [9]. `<img src="IMAGE URL" foo="bar" />`
*
* ... and the uppercased version of them, and the single-quoted version of them
*
*/
matches = /<img .*?src=[\'"]([^\'"]+?)[\'"].*? *\/?>/i.exec(data);
return matches ? matches[1] : noImage;

}

Penggunaan

var img = '<img src="' + getFirstImageURL(sourceText, 'img/no-image.png') + '">';
document.write(img);

sourceText cuma contoh. Anda harus mengambilnya dari konten posting Anda, misalnya dengan cara ini:

var sourceText = document.querySelector('.post-body').innerHTML;

Rabu, 19 Februari 2014

Simple Text Editor Library

Markdown Text Editor
Editor Teks untuk Format Markdown

Pembuatan perpustakaan JavaScript ini dikhususkan untuk menangani aplikasi-aplikasi editor teks berbasis elemen <textarea>. Target awal ingin Saya jadikan sebagai pendukung aplikasi editor teks Markdown, tapi Anda juga bisa menggunakan ini untuk membuat aplikasi editor teks sekelas MarkItUp! jika mau:

Demo

NB: Butuh judul posting berbahasa Indonesia untuk ini.

Kamis, 13 Februari 2014

Regex untuk Validasi Tag HTML

<("[^"]*"|'[^']*'|[^'">])*>

Cocok untuk pola ini:

  1. <input value='>'>
  2. <input value='<'>
  3. <a href="http://www.nama_web.com">
  4. <br>, <br/>
  5. <input value="'" id="test">, <input value='"' id='test'>

Jumat, 07 Februari 2014

PHP Flat-File GuestBook

Flat-File Guestbook in PHP
Tampilan Buku Tamu

Saya membuat aplikasi Buku Tamu tanpa basis data dengan PHP. Semua data disimpan di dalam sebuah file TXT sebagai pengganti basis data. Ide asli diambil dari sini.

Pada versi Saya, Saya tidak menggunakan captcha gambar, melainkan hanya menggunakan tantangan matematika yang lebih sederhana namun relatif aman. Kode ini dituliskan secara baru, mulai dari awal dan bukan merupakan hasil modifikasi. Beberapa fitur baru yang Saya berikan:

  • Memungkinkan pengguna untuk menambahkan URL.
  • Tanggal penerbitan tersedia, dan akan ditampilkan di pojok kanan atas secara normal.
  • Memungkinkan pengguna untuk membagikan pesan secara individual melalui tautan permanen.
  • Memungkinkan administrator untuk membuat “database” baru tanpa harus menghapus data yang lama.
  • Memungkinkan administrator dan pengguna untuk memuat data lama melalui parameter URL berupa nama file.
  • Sistem keamanan yang lebih baik:
    • Pengguna wajib menjawab tantangan matematika sederhana.
    • Pembatasan jumlah karakter pada setiap bidang.
    • Secara otomatis mengubah kode HTML menjadi entitas HTML untuk keamanan, dan hanya akan menerjemahkan kode HTML yang diperbolehkan saja.
    • Pesan kesalahan akan tampil lebih jelas, serta data yang telah pengguna masukkan sebelumnya ke dalam formulir akan tetap tersimpan di sana sebelum pengguna berhasil mengirimkan pesannya.
    • Tautan di dalam pesan akan terhapus secara otomatis.

Ekstrak file unduhan untuk mendapatkan folder guestbook. Masukkan folder tersebut beserta isinya ke dalam folder public_html atau www pada server lokal Anda. Tidak perlu konfigurasi khusus. Sekali pasang langsung jalan! Jika Anda ingin melakukan konfigurasi, maka itu hanya sebatas pada penamaan “database”, pengaturan panjang karakter maksimal dan penyesuaian teks pesan peringatan.

Jika sudah selesai, buka alamat http://localhost/guestbook/index.php pada peramban untuk melihat hasilnya.

Tidak ada fitur emotikon. Terlalu berlebihan untuk diterapkan pada aplikasi yang sederhana dan bukan merupakan kebutuhan primer. Anda bisa dengan mudah membuatnya sendiri melalui perintah preg_replace() seperti ini:

$message = preg_replace(
array(
'/( |>)\:\-?\)/',
'/( |>)\:\-?D/',
'/( |>)\:\-?\)/',
...
...
),
array(
'$1<img src="emoticons/smile.gif" alt=":)">',
'$1<img src="emoticons/laugh.gif" alt=":D">',
'$1<img src="emoticons/sad.gif" alt=":(">',
...
...
),
$message);

Ketika Data Dirasa telah Penuh

Ketika Anda merasa bahwa file TXT yang Anda buat sudah terlalu besar ukurannya, atau membuat proses muat halaman menjadi lambat, Anda bisa mengatasinya dengan cara mengganti nilai $database dengan nama yang baru untuk menciptakan file TXT baru tanpa harus menghapus yang lama. Untuk memuat data yang lama ke dalam halaman buku tamu agar bisa ditampilkan ke publik (katakanlah Anda telah membuat pengaturan khusus agar pengguna tidak bisa melihat file dengan format TXT), Anda bisa menambahkan parameter data dengan nilai berupa nama “database” seperti ini:

http://localhost/guestbook/index.php?data=database-003

Atau kalau memang data-data di dalam buku tamu Anda itu tidak penting, Anda bisa menghapus file tersebut begitu saja kalau mau. Semua kode sudah Saya lengkapi dengan penjelasan. Silakan dipelajari atau digunakan jika dirasa berguna.

Rabu, 05 Februari 2014

Tab & Untab

Fungsi ini memungkinkan Anda untuk melakukan perintah indentasi atau outdentasi pada lebih dari satu baris teks sekaligus di dalam elemen <textarea>:

(function() {

var tabCharacter = ' '; // Use `\t` or multiple space character

var select = function(start, end, target) {
target.focus();
target.setSelectionRange(start, end);
};

window._tab = function(target) {

var start = target.selectionStart,
end = target.selectionEnd,
value = target.value,
selections = value.substring(start, end).split('\n');

for (var i = 0, len = selections.length; i < len; ++i) {
selections[i] = tabCharacter + selections[i];
}

target.value = value.substring(0, start) + selections.join('\n') + value.substring(end);

// re-select text after tabbing
var selectEnd = (end + (tabCharacter.length * selections.length));
if (start == end) {
select(selectEnd, selectEnd, target);
} else {
select(start, selectEnd, target);
}

};

window._untab = function(target) {

var start = target.selectionStart,
end = target.selectionEnd,
value = target.value,
pattern = new RegExp("^" + tabCharacter),
edits = 0;

if (start == end) { // single line

while (start > 0) {
if(value.charAt(start) == '\n') {
start++;
break;
}
start--;
}

var portion = value.substring(start, end),
matches = portion.match(pattern);

if (matches) {
target.value = value.substring(0, start) + portion.replace(pattern, "") + value.substring(end);
end--;
}

// set caret position after tabbing
var selectEnd = end <= start ? end : end - tabCharacter.length + 1;
select(selectEnd, selectEnd, target);

} else { // multiline

var selections = value.substring(start, end).split('\n');

for (var i = 0, len = selections.length; i < len; ++i) {
if (selections[i].match(pattern)) {
edits++;
selections[i] = selections[i].replace(pattern, "");
}
}

target.value = value.substring(0, start) + selections.join('\n') + value.substring(end);

// re-select text after tabbing
select(start, (edits > 0 ? end - (tabCharacter.length * edits) : end), target);

}

};

})();

Penggunaan

Dengan tombol:

<button onclick="_tab(document.getElementById('ID-TEXTAREA'));">Tab</button>
<button onclick="_untab(document.getElementById('ID-TEXTAREA'));">Untab</button>

Dengan tombol Tab dan Shift + Tab pada papan kunci:

document.getElementById('ID-TEXTAREA').onkeydown = function(e) {
// Shift + Tab ditekan
if (e.shiftKey && e.keyCode == 9) {
_untab(this);
return false;
}
// Tab ditekan
if (e.keyCode == 9) {
_tab(this);
return false;
}
};

Terkait: Daftar Snippet untuk Implementasi DOM Range API

Minggu, 22 Desember 2013

Membuat Posting Layar Penuh

Mode layar penuh.
Mode layar penuh.

Saya membuat sebuah aplikasi/widget kecil untuk membuat posting di blog menjadi memiliki alternatif tampilan “layar penuh”. Tidak benar-benar layar penuh sebenarnya, karena widget ini hanya bekerja dengan cara menyisipkan tabir baru berisi duplikat judul dan konten posting. Kalau Anda ingin membuat fitur full screen sungguhan yang bisa memenuhi seluruh layar, Anda bisa mempelajari API JavaScript ini ⇒ MDN - Using Full Screen Mode

Untuk memasang widget ini, masuklah ke halaman editor HTML Templat, lalu letakkan kode ini di atas </body>:

<b:if cond='data:blog.pageType == &quot;item&quot;'>
<script src='http://dte-project.googlecode.com/svn/trunk/full-screen.min.js'/>
<script>
//<![CDATA[
postFullScreen({
titleSource: document.querySelector('.post-title'),
contentSource: document.querySelector('.post-body'),
background: "#fff",
color: "inherit",
fontSize: "120%",
padding: 50,
maxWidth: 750,
openText: "Full Screen Mode",
closeText: "Exit full screen mode",
appendButtonTo: null,
beforeInit: null,
afterInit: null
});
//]]>
</script>
</b:if>

Atau Saya sarankan lebih baik letakkan kode di atas sedekat mungkin dengan posting. Lebih tepatnya di bagian paling bawah dari posting:

<b:section class='main' id='main' showaddelement='no'>
<b:widget id='Blog1' locked='true' title='Posting Blog' type='Blog'> … </b:section>
</b:section>
<!-- Letakkan di sini -->

Klik Simpan Templat.

Konfigurasi

OpsiKeterangan
titleSourceSelektor elemen HTML dimana di dalamnya berisi teks judul. Di atas Saya menggunakan selektor document.querySelector('.post-title') untuk memperoleh teks judul dari dalam elemen <h3 class='post-title'></h3>. Sebagai alternatif, Anda bisa mencoba untuk menggunakan selektor document.title untuk memperoleh judul dari address bar.
contentSourceSelektor elemen HTML dimana di dalamnya terdapat konten artikel/posting. Pengaturannya sama persis dengan opsi titleSource.
backgroundDigunakan untuk menentukan warna latar tabir layar penuh.
colorDigunakan untuk menentukan warna teks mode layar penuh. inherit artinya warna menyesuaikan dengan warna teks posting.
fontSizeDigunakan untuk menentukan besar teks di artikel layar penuh.
paddingDigunakan untuk menentukan padding tabir layar penuh.
maxWidthDigunakan untuk menentukan lebar maksimal area artikel layar penuh.
openTextDigunakan untuk menentukan teks tombol pemicu layar penuh.
closeTextDigunakan untuk menentukan teks tombol penutup tampilan layar penuh.
createButtonDigunakan untuk membuat tombol kustom. Lihat penjelasan di bawah.
appendButtonToNilai berupa selektor elemen HTML. Jika nilainya null, tombol akan secara otomatis disisipkan di bawah posting. Jika nilainya false, tombol tidak akan disisipkan secara otomatis (bermanfaat jika Anda ingin membuat tombol pemicu tersendiri secara terpisah).
beforeInitLihat penjelasan di bawah.
afterInitLihat penjelasan di bawah.

Penjelasan Ekstra

createButton

Opsi ini digunakan sebagai alternatif jika Anda tidak suka dengan tampilan tombol pemicu layar penuh secara normal. Anda bisa memanfaatkan opsi ini untuk menentukan/membuat elemen tombol kustom. Sebagai contoh di sini Saya menggunakan elemen tautan sebagai tombol:

var buttonMarkup = document.createElement('a');
buttonMarkup.className = "custom-button";
buttonMarkup.style.display = "block";
buttonMarkup.style.marginTop = "20px";

postFullScreen({
openText: "Layar Penuh!",
createButton: buttonMarkup
});

/*

akan menghasilkan ini:

<a class="custom-button" style="display:block;margin-top:20px;">Layar Penuh!</a>

*/

Atau Anda juga bisa menentukan nilainya sebagai objek yang sudah ada. Sebagai contoh Anda membuat tombol pemicu secara manual di tempat tertentu, misalnya di sidebar:

<aside>
...
<button id="full-screen-button">Layar Penuh</button>
...
...
</aside>

Kemudian Anda bisa melakukan ini untuk membuat tombol tersebut menjadi aktif:

postFullScreen({
createButton: document.getElementById('full-screen-button'),
appendButtonTo: false
});

Jangan lupa untuk mengatur opsi appendButtonTo menjadi false karena jika tidak tombol tersebut mungkin akan berpindah tempat. Secara umum akan berpindah ke bagian akhir posting:

appendButtonTo

Opsi ini digunakan untuk menentukan ke mana tombol pemicu tampilan layar penuh akan disisipkan. Berikut ini adalah sebuah contoh jika Anda ingin menyisipkan tombol pemicu layar penuh di dalam elemen #button-container:

<div id="button-container"></div>
postFullScreen({
...
appendButtonTo: document.getElementById('button-container')
});

beforeInit dan afterInit

Ini adalah opsi untuk membuat fungsi bebas yang akan tereksekusi sebelum (untuk beforeInit) dan sesudah (untuk afterInit) markup tabir tersisip ke blog. Yang paling berguna adalah beforeInit. Fungsi ini bisa Anda gunakan untuk memastikan bahwa manipulasi konten posting yang dilakukan oleh JavaScript telah dilakukan sebelum widget ini tereksekusi. Misalnya mengenai Syntax Highlighter atau JavaScript emotikon. Jika Syntax Highlighter atau JavaScript emotikon tidak diaktifkan sebelum widget ini aktif, maka kemungkinannya posting-posting kode yang berada di dalam artikel layar penuh tidak akan berwarna, dan emotikon-emotikon di dalam artikel tidak akan berubah menjadi gambar:

postFullScreen({
beforeInit: function() {
repText('post-12345');
hljs.initHighlighting();
},
afterInit: function() {
alert('OK!');
}
});

Pengguna JQuery

Jangan lupa untuk menambahkan indeks [0] setelah selektor jika Anda menggunakan API selektor elemen JQuery:

postFullScreen({
titleSource: $('.post-title')[0],
contentSource: $('.post-body')[0]
});

Rabu, 18 Desember 2013

Panduan Mendesain Elemen-Elemen Formulir HTML dari Awal

HTML Form Elements
Elemen-elemen formulir.

Mendesain elemen UI itu bukan cuma soal menentukan efek gradiasi yang bagus, efek bayangan yang realistis dan juga pewarnaan yang cocok dengan lingkungan. Web tidak sama dengan sekedar mendesain grafis, yang artinya bahwa semuanya tidak akan bisa semudah itu dibuat menjadi tampak sama pada semua peramban. Setiap peramban memiliki spesifikasinya sendiri-sendiri, dan terkadang mereka juga memiliki spesifikasi yang sangat berbeda, yang menurut kita mungkin sangat mengganggu. Namun tentunya spesifikasi tersebut memiliki tujuan tersendiri yang sangat khusus untuk peramban terkait agar bisa bekerja dengan baik/lebih baik dibandingkan dengan peramban-peramban yang lain. Kita tidak bisa melakukan apa-apa.

Membuat desain tampilan menjadi tampak sama —atau setidaknya nyaris sama— itu tidak mudah untuk elemen-elemen formulir. Anda harus mengikuti beberapa tahapan pembentukan ulang… dan yang terpenting adalah mengenai prioritas dalam hal kestabilan tampilan dibandingkan dengan keindahan tampilan.

Memulai dengan Tahap Pembentukan Ulang

Langkah awal yang harus Anda lakukan adalah menentukan posisi, jarak, padding dan beberapa pengaturan warna serta tipe fon secara global sebisa mungkin ke semua elemen formulir yang ada:

button,
input,
select,
textarea {
display:inline-block; /* alternatif yang lebih baik dibandingkan `display:inline` */
vertical-align:middle; /* posisikan elemen ke tengah secara vertikal terhadap teks */
width:170px; /* tentukan lebar elemen secara umum */
margin:1px 0; /* tentukan `margin` elemen secara umum */
padding:4px; /* tentukan `padding` elemen secara umum */
font:normal normal 13px/normal Arial,Sans-Serif; /* tentukan tipe fon secara umum */
color:#333; /* tentukan warna teks secara umum */
line-height:normal; /* tentukan `line-height` secara umum (deklarasi `line-height` pada selektor `font` di atas biasanya tidak bekerja pada elemen `<button>`) */
background-color:white; /* tentukan warna latar secara umum */
border:1px solid #333; /* tentukan `border` secara umum */

/* deklarasikan `box-sizing` yang seragam */
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;

/* hapus outline jika mungkin */
outline:none;
outline-offset:-2px;
}

Pada kode di atas Saya juga menentukan ukuran lebar sebesar 170px secara global. Penentuan lebar elemen ini sebenarnya Saya tujukan hanya kepada elemen select dan elemen input yang berfungsi untuk menyisipkan teks (misalnya elemen formulir bertipe date, email, number, tel, text dan url). Namun karena Saya menerapkannya pada selektor CSS berupa input tanpa adanya penambahan atribut type secara spesifik, maka deklarasi lebar ini juga akan mempengaruhi semua elemen input yang tidak kita kehendaki, misalnya pada elemen input bertipe button dan checkbox. Oleh karena itulah setelah pendeklarasian tersebut dilakukan, kita juga harus mengembalikan ukuran lebar pada elemen-elemen formulir yang tidak kita kehendaki memiliki ukuran lebar tetap.

Kebetulan di sini Saya mengatur nilai lebar kembali menjadi auto pada elemen-elemen formulir berupa tombol, sehingga pada saat yang bersamaan Saya juga bisa menambahkan beberapa warna baru pada elemen-elemen ini untuk membedakan tampilannya dengan elemen-elemen formulir berupa masukan teks:

button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
width:auto; /* mengembalikan ukuran lebar ke keadaan semula */
background-color:#333; /* tentukan warna latar yang berbeda untuk elemen-elemen tombol */
color:white; /* tentukan warna teks yang berbeda untuk elemen-elemen tombol */

/* buat `padding` kiri dan kanan menjadi lebih lebar untuk membuatnya lebih gemuk */
padding-right:8px;
padding-left:8px;

font-weight:bold; /* buat teks menjadi tebal */
cursor:pointer; /* ubah kursor menjadi `pointer` untuk kenyamanan */
border-color:transparent; /* opsional */
}

box-sizing

Sedikit catatan mengenai deklarasi box-sizing yang Saya tambahkan. Itu berfungsi untuk mengatasi masalah ukuran lebar yang tidak seragam terutama pada elemen formulir berupa masukan teks dan selectbox:

Text Input and Select Element without CSS `box-sizing`
Membandingkan ukuran elemen input dengan elemen select yang sudah dimodifikasi tanpa adanya deklarasi box-sizing yang seragam.

Dari gambar di atas terlihat bahwa meskipun keduanya sama-sama Saya beri ukuran lebar sebesar 170 piksel, padding sebesar 2 piksel dan border setebal 1 piksel (gambar perbandingan yang ke dua), pada kenyataannya elemen masukan teks akan menghasilkan lebar sebesar 173 piksel (border-left-width + padding-left + width + padding-right + border-right-width ), sedangkan elemen selectbox akan memiliki lebar sebesar 170 piksel (width ). Ini berarti bahwa elemen selectbox telah memiliki deklarasi box-sizing sebagai border-box secara normal, sedangkan elemen yang lain tidak —telah ditentukan oleh User Agent Stylesheet.

Anda bisa memilih untuk menentukan nilai properti ini menjadi border-box atau padding-box karena tujuan utama pendeklarasian properti ini memang hanya untuk menyamakan logika CSS Box-Model mereka saja. Tapi Saya sarankan untuk menggunakan border-box saja karena deklarasi ini memiliki satu keuntungan lain yaitu akan mempermudah Anda di dalam mengatasi masalah penentuan lebar elemen menuju ukuran 100% dengan hasil tampilan yang benar.

Kembalikan semua ukuran lebar elemen input bertipe checkbox dan radio serta image. Hilangkan juga deklarasi border, padding dan background yang kita deklarasikan sebelumnya:

/* hilangkan nilai `width`, `border`, `padding`, `background` yang telah dibuat sebelumnya pada elemen-elemen ini */
input[type="checkbox"],
input[type="image"],
input[type="radio"] {
width:auto;
padding:0;
background:none;
border:none;
cursor:pointer;
}

Setelah itu atur posisi elemen label menjadi berada di tengah secara vertikal. Atur juga tipe kursor menjadi pointer untuk menambahkan kenyamanan bagi pengguna. Bisa juga digabungkan dengan select, input[type="color"] dan input[type="file"] untuk meringkas kode CSS (meskipun properti display dan vertical-align sebenarnya sudah ditentukan sebelumnya):

input[type="color"],
input[type="file"],
label,
select {
display:inline-block;
vertical-align:middle;
cursor:pointer;
}

Atau pakai ini saja untuk CSS yang lebih panjang namun lebih logis:

input[type="color"],
input[type="file"],
select {cursor:pointer}

label {
display:inline-block;
vertical-align:middle;
cursor:pointer;
}

Elemen Tombol Tampak Lebih Besar di Firefox

Mungkin Anda pernah mengalami ini. Masalahnya bukan karena kode CSS Anda yang salah, tetapi karena Firefox memiliki elemen DOM bayangan yang mengitari bagian sebelah dalam elemen button dan elemen input bertipe button, submit atau reset seperti ini, yang telah membuat ukuran tombol menjadi lebih gemuk di Firefox:

::-moz-focus-inner
::-moz-focus-inner pada peramban Firefox.

CSS ini bisa mengatasi masalah tersebut:

button::-moz-focus-inner,
input::-moz-focus-inner {
margin:0;
padding:0;
border:none;
outline:none;
}

Textarea di Internet Explorer

Internet Explorer secara normal memiliki tampilan elemen textarea yang akan tetap meninggalkan scrollbar vertikal meskipun isinya kosong. Gunakan deklarasi overflow:auto untuk menghilangkan scrollbar pada elemen ini agar tampilannya sama dengan apa yang terlihat di peramban lain:

textarea {overflow:auto}

Beberapa deklarasi lain yang umum untuk membuat elemen ini menjadi lebih stabil:

textarea {
overflow:auto;
display:block; /* set sebagai elemen blok */
width:100%; /* buat lebarnya menjadi 100% */
resize:vertical; /* agar `textarea` hanya bisa diubah ukurannya secara vertikal (lainnya: `both`, `horizontal`, `none`) */
}

Efek :focus, :hover dan :active

Tentukan efek fokus secara global. Target utamanya adalah elemen input bertipe date, email, number, tel, text dan url serta select dan textarea:

input:focus,
select:focus,
textarea:focus {background-color:#ffa}

Setelah itu buat efek :focus, :hover dan :active untuk elemen-elemen tombol:

/* focus */
button:focus,
input[type="button"]:focus,
input[type="reset"]:focus,
input[type="submit"]:focus {background-color:#00f}

/* hover */
button:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {background-color:#444}

/* active */
button:active,
input[type="button"]:active,
input[type="reset"]:active,
input[type="submit"]:active {background-color:#111}

fieldset dan legend

CSS untuk mengatur tampilan fieldset dan legend:

fieldset {
margin:0 0 1em;
padding:1em;
border:1px solid #333;
}

legend {
margin:0;
padding:0 10px;
font-weight:bold;
}

Efek :disabled

Bisa menggunakan selektor pseudo kelas :disabled, tapi Saya sarankan untuk menggunakan selektor atribut saja yang memiliki dukungan peramban lebih bagus:

button[disabled],
input[disabled],
select[disabled],
textarea[disabled] {
opacity:.7; /* buat warnanya menjadi kabur */
cursor:default; /* fallback */
cursor:not-allowed; /* CSS3 */
}

Efek :readonly

Hanya untuk elemen formulir masukan teks dan area teks:

input[type="date"][readonly],
input[type="email"][readonly],
input[type="number"][readonly],
input[type="tel"][readonly],
input[type="text"][readonly],
input[type="url"][readonly],
textarea[readonly],
input[type="date"][readonly]:focus,
input[type="email"][readonly]:focus,
input[type="number"][readonly]:focus,
input[type="tel"][readonly]:focus,
input[type="text"][readonly]:focus,
input[type="url"][readonly]:focus,
textarea[readonly]:focus {
background-color:#eee;
cursor:default;
}

Mengubah Warna Placeholder

Berikut ini beberapa selektor CSS elemen pseudo dengan prefiks khusus yang berbeda-beda pada setiap peramban. Untuk alasan yang tidak Saya tahu, semua selektor ini tidak bisa digabungkan dengan tanda koma:

::-webkit-input-placeholder {color:#999} /* WebKit */
:-ms-input-placeholder {color:#999} /* IE 9+ */
::-moz-placeholder {color:#999} /* Firefox 19+ */
:-moz-placeholder {color:#999} /* Firefox 18- */
:placeholder {color:#999} /* W3C */

:focus::-webkit-input-placeholder {color:#b9b989}
:focus:-ms-input-placeholder {color:#b9b989}
:focus::-moz-placeholder {color:#b9b989}
:focus:-moz-placeholder {color:#b9b989}
:focus:placeholder {color:#b9b989}

Yap!

Itu adalah garis besarnya. Beberapa yang lain di bawah ini mungkin bisa Anda tambahkan tapi ini spesifik untuk peramban WebKit:

/* mengubah tampilan simbol panah pada elemen `<select>` */
select {
-webkit-appearance:none;
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAASCAYAAAC0EpUuAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB90MEg4aKjycyUMAAABJSURBVDjLYzQ0NPzPQCE4d+4cIzKfiYEGYNTQkWwoC450h1ODkZEReS7FpZEYA/F6H90AYg0kGKYwg0gxkKiIItXA0XQ6hAwFADv7Cz1+RA3TAAAAAElFTkSuQmCC');
background-repeat:no-repeat;
background-position:100% 50%;
}

select[multiple],
select[size] {background-image:none}

/* mengubah tampilan tombol pada elemen `<input type="file">` */
input[type="file"] {-webkit-appearance:none}
input[type="file"]::-webkit-file-upload-button {
-webkit-appearance:none;
display:inline-block;
vertical-align:top;
background-color:#333;
color:white;
font-size:11px;
font-weight:bold;
margin:0;
padding:2px 5px;
border:none;
cursor:pointer;
}

/* `<input type="range">` */
input[type="range"] {
-webkit-appearance:none;
height:0;
padding:1px 0;
border:1px solid #333;
background-color:white;
}

input[type="range"]::-webkit-slider-thumb {
-webkit-appearance:none;
margin:0;
padding:0;
border:none;
background-color:#333;
width:10px;
height:18px;
cursor:w-resize;
}

input[type="range"]::-webkit-slider-thumb:hover {background-color:#444}
input[type="range"]::-webkit-slider-thumb:active {background-color:#111}

Beberapa tautan yang Saya sarankan untuk mempelajari hal-hal terkait Shadow DOM:


Berikut ini adalah hasil akhir untuk semua hal yang telah Saya jelaskan di atas. Ini bisa dikatakan sebagai kerangka dasar, sehingga Anda bisa cukup salin-tempel kode ini saja dengan aman ke dalam berkas CSS pada setiap awal mendesain:

/* TAHAP PEMBENTUKAN ULANG */

button,
input,
select,
textarea {
display:inline-block; /* alternatif yang lebih baik dibandingkan `display:inline` */
vertical-align:middle; /* posisikan elemen ke tengah secara vertikal terhadap teks */
width:170px; /* tentukan lebar elemen secara umum */
margin:1px 0; /* tentukan `margin` elemen secara umum */
padding:4px; /* tentukan `padding` elemen secara umum */
font:normal normal 13px/normal Arial,Sans-Serif; /* tentukan tipe fon secara umum */
color:#333; /* tentukan warna teks secara umum */
line-height:normal; /* tentukan `line-height` secara umum (deklarasi `line-height` pada selektor `font` di atas biasanya tidak bekerja pada elemen `<button>`) */
background-color:white; /* tentukan warna latar secara umum */
border:1px solid #333; /* tentukan `border` secara umum */

/* deklarasikan `box-sizing` yang seragam */
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;

/* hapus outline jika mungkin */
outline:none;
outline-offset:-2px;
}


/* TOMBOL */

button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
width:auto; /* mengembalikan ukuran lebar ke keadaan semula */
background-color:#333; /* tentukan warna latar yang berbeda untuk elemen-elemen tombol */
color:white; /* tentukan warna teks yang berbeda untuk elemen-elemen tombol */

/* buat `padding` kiri dan kanan menjadi lebih lebar untuk membuatnya lebih gemuk */
padding-right:8px;
padding-left:8px;

font-weight:bold; /* buat teks menjadi tebal */
cursor:pointer; /* ubah kursor menjadi `pointer` untuk kenyamanan */
border-color:transparent; /* opsional */
}


/* PERBAIKI DIMENSI BEBERAPA ELEMEN INI */

/* hilangkan nilai `width`, `border`, `padding`, `background` yang telah dibuat sebelumnya pada elemen-elemen ini */
input[type="checkbox"],
input[type="image"],
input[type="radio"] {
width:auto;
padding:0;
background:none;
border:none;
cursor:pointer;
}

/*
Anda mungkin akan membutuhkan ini untuk memastikan agar
posisi checkbox dan radio bisa berada tepat di tengah secara vertikal.
Saya mengomentari deklarasi CSS ini dan tidak menjelaskannya
secara khusus di atas karena Saya pikir ini adalah
praktek Magic Number yang tidak disarankan.

input[type="checkbox"],
input[type="radio"] {
position:relative;
top:-2px;
}

*/

/* set tipe kursor ke `pointer` untuk kenyamanan */
input[type="color"],
input[type="file"],
label,
select {
display:inline-block;
vertical-align:middle;
cursor:pointer;
}

/* textarea */
textarea {
overflow:auto;
display:block; /* set sebagai elemen blok */
width:100%; /* buat lebarnya menjadi 100% */
resize:vertical; /* agar `textarea` hanya bisa diubah ukurannya secara vertikal (lainnya: `both`, `horizontal`, `none`) */
}


/* MENORMALKAN ::-moz-focus-inner PADA TOMBOL-TOMBOL DI FIREFOX */

button::-moz-focus-inner,
input::-moz-focus-inner {
margin:0;
padding:0;
border:none;
outline:none;
}


/* PSEUDO KELAS - :hover, :focus, :active */

/* focus */
input:focus,
select:focus,
textarea:focus {background-color:#ffa}

/* focus */
button:focus,
input[type="button"]:focus,
input[type="reset"]:focus,
input[type="submit"]:focus {background-color:#00f}

/* hover */
button:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {background-color:#444}

/* active */
button:active,
input[type="button"]:active,
input[type="reset"]:active,
input[type="submit"]:active {background-color:#111}


/* FIELDSET & LEGEND */

fieldset {
margin:0 0 1em;
padding:1em;
border:1px solid #333;
}

legend {
margin:0;
padding:0 10px;
font-weight:bold;
}


/* DISABLED */

button[disabled],
input[disabled],
select[disabled],
textarea[disabled] {
opacity:.7; /* buat warnanya menjadi kabur */
cursor:default; /* fallback */
cursor:not-allowed; /* CSS3 */
}


/* READONLY */

input[type="date"][readonly],
input[type="email"][readonly],
input[type="number"][readonly],
input[type="tel"][readonly],
input[type="text"][readonly],
input[type="url"][readonly],
textarea[readonly],
input[type="date"][readonly]:focus,
input[type="email"][readonly]:focus,
input[type="number"][readonly]:focus,
input[type="tel"][readonly]:focus,
input[type="text"][readonly]:focus,
input[type="url"][readonly]:focus,
textarea[readonly]:focus {
background-color:#eee;
cursor:default;
}


/* PLACEHOLDER */

::-webkit-input-placeholder {color:#999} /* WebKit */
:-ms-input-placeholder {color:#999} /* IE 9+ */
::-moz-placeholder {color:#999} /* Firefox 19+ */
:-moz-placeholder {color:#999} /* Firefox 18- */
:placeholder {color:#999} /* W3C */

:focus::-webkit-input-placeholder {color:#b9b989}
:focus:-ms-input-placeholder {color:#b9b989}
:focus::-moz-placeholder {color:#b9b989}
:focus:-moz-placeholder {color:#b9b989}
:focus:placeholder {color:#b9b989}

Setiap kali Anda mendesain elemen atom, selalu pastikan untuk menyelesaikan masalah-masalah di atas terlebih dahulu. Jika tidak, mungkin Anda akan mengalami berbagai kesulitan saat menangani masalah penampilan pada peramban-peramban tertentu.

Selain itu setidaknya Anda baru bisa/boleh mendesain tampilan elemen-elemen formulir setelah Anda menyelesaikan masalah tampilan elemen-elemen artikel. Setelah itu, Anda bisa memulai untuk menambahkan efek gradiasi, bayangan dan menyesuaikan warna-warna elemen-elemen formulir yang ada sesuai kehendak: