Thursday, May 30, 2013

Aksesibilitas pada Soal Pilihan Ganda Online

Example of Accessible QA Form

Berbicara mengenai elemen formulir, umumnya elemen radio dan checkbox akan menjadi jenis elemen yang cukup sulit untuk ditangani oleh pihak pengguna karena ukurannya yang sangat kecil. Contoh sederhana:

<input type="radio" name="o"> Pilihan 1
<br>
<input type="radio" name="o"> Pilihan 2

Formulir di atas memang bekerja, tetapi tidak cukup nyaman untuk digunakan. Area yang bisa diklik hanya terfokus pada elemen radio saja yang ukurannya sangat kecil:

Aksesibilitas elemen radio yang kurang baik tanpa adanya elemen label.
Area pengecekan hanya terbatas pada elemen radio yang berukuran sangat kecil.

Mungkin tidak masalah jika orang yang mengisi formulir tersebut adalah orang-orang yang masih muda. Tetapi bagaimana jika yang mengisi formulir tersebut adalah para orangtua dan lanjut usia? Karena bagi mereka, mengarahkan mouse saja sudah kewalahan, apalagi mengeklik elemen radio yang ukurannya kecil seperti itu!

Selalu Ingat untuk Menambahkan Elemen Label

Untuk memperluas area pengecekan, kita bisa membungkus setiap opsi formulir dengan elemen label seperti ini:

<label><input type="radio" name="o"> Pilihan 1</label>
<br>
<label><input type="radio" name="o"> Pilihan 2</label>

Cara ini memungkinkan teks (atau elemen apa saja) yang berada di dalam elemen label tersebut untuk bisa bekerja sebagai pemicu perubahan kondisi radio yang merupakan anak dari label tersebut:

Aksesibilitas elemen radio yang lebih baik dengan penambahan elemen label.
Area pengecekan menjadi lebih luas, meliputi radio dan teks di sampingnya.

Kursor

Berikan elemen label dan semua jenis tombol dengan kursor jari telunjuk untuk meningkatkan kenyamanan:

input[type="button"],
input[type="submit"],
input[type="reset"],
button,
label {cursor:pointer}

Efek Timbal Balik

Perubahan warna saat opsi disentuh dan saat opsi terseleksi, semua itu akan memberikan rasa keyakinan kepada setiap pengguna yang sedang mengisi formulir Anda:

label:hover {background-color:whitesmoke}
label:active {background:none}
label.selected {background-color:forestgreen} /* Kelas `.selected` akan diciptakan oleh JavaScript */

Demonstrasi

Berikut ini adalah sebuah demonstrasi soal pilihan ganda online dengan akses jawaban yang mudah untuk kenyamanan pengguna:

HTML

<form class="qa-form" id="qa-form" action="...">
    <ol>
        <li>
            <p>Uraian pertanyaan di sini ...</p>
            <label><input type="radio" name="a-1"> Jawaban 1</label>
            <label><input type="radio" name="a-1"> Jawaban 2</label>
            <label><input type="radio" name="a-1"> Jawaban 3</label>
            ...
        </li>
        <li> ... </li>
    </ol>
</form>

CSS

.qa-form {padding:1em 1em 2em}

.qa-form ol,
.qa-form li,
.qa-form p,
.qa-form input,
.qa-form label {
  margin:0;
  padding:0;
}

.qa-form ol {
  list-style:decimal outside;
  margin:0 0 2em 3em;
}

.qa-form p {
  margin:1em 0;
  clear:both;
}

.qa-form label {
  display:block;
  width:300px;
  cursor:pointer;
  overflow:hidden;
  padding:5px 10px 5px 6px;
  margin:0 0 2px;
  line-height:100%;
  border-radius:20px;
}

.qa-form label input {
  outline:none;
  vertical-align:top;
  cursor:inherit;
}

.qa-form button {cursor:pointer}
.qa-form label:hover {background-color:whitesmoke}
.qa-form label:active {background:none}

.qa-form label.selected {
  background-color:forestgreen;
  color:white;
}

jQuery

// Fungsi ini digunakan untuk menambahkan/menyingkirkan
// kelas `.selected` pada elemen `<label>`
// berdasarkan kondisi radio di dalamnya
$(document).ready(function() {
    $('#qa-form :radio').on("change", function() {
        $(this).parent()[this.checked ? "addClass" : "removeClass"]('selected').siblings().removeClass('selected');
    });
    $('#qa-form :reset').on("click", function() {
        $(this).closest('form').find('label').removeClass('selected').children().prop('checked', false);
    });
});

Lihat Demo

Kesimpulan

Selalu pastikan bahwa pengguna bisa merasa nyaman dengan apa yang Anda berikan untuk mereka gunakan. Berikan efek timbal balik yang tegas kepada pengguna agar mereka yakin dengan apa yang telah mereka putuskan, sehingga hal-hal seperti kegagalan tes karena kesalahan antarmuka pengguna tidak akan terjadi.

Labels: , , ,

Tuesday, May 28, 2013

B1:A · Template Blogger Minimalis Responsif

Homepage of B1:A

B1:A adalah templat Blogger responsif minimalis dua kolom. Pemilihan font Saya fokuskan pada Source Sans Pro, Oswald dan font ikon dari Fontawesome.

Lihat Gambar Demo Unduh Template

Gambar demo yang lebih besar seharusnya bisa Anda dapatkan di dalam file unduhan.

Konfigurasi

1. Mengubah Teks “Read More”

Masuk ke halaman Tata Letak, kemudian lihat pada widget Posting Blog. Klik tombol pengeditan yang terletak di sebelah pojok kanan bawah. Teks “Read More” bisa diganti pada bagian ini:

Blogger Post Widget Editor
Editor widget posting.

2. Mengubah Teks “Search”

Saat Anda berada di halaman Editor HTML templat, pastikan kursor teks sedang aktif di dalam area kode. Tekan CTRL

+

F

lalu ketik class='submit-button. Kode yang Saya beri tanda di bawah ini adalah yang harus diganti:

<button class='submit-button' type='submit'><i class='icon-search'/> Search</button>

3. Memodifikasi Menu Navigasi

Tekan CTRL

+

F

lalu ketik id='site-nav untuk menemukan deret kode seperti ini:

<nav class='nav' id='site-nav'>
  <ul>
    <li><a class='home-menu' expr:href='data:blog.homepageUrl' title='Home'><i class='icon-home icon-2x'/><span class='screen-reader'> Home</span></a></li>
    <li><a href='#'>About</a></li>
    <li><a href='#'>Archive</a></li>
    ...

4. Mematikan Fitur Responsif

Untuk yang tidak suka dengan tema responsif, pada tag <html> terdapat atribut kelas seperti ini:

<html expr:class='data:blog.languageDirection + &quot; no-js rwd&quot;' expr:dir='data:blog.languageDirection'>

Untuk mematikan fitur responsif, buang kode yang Saya beri tanda.

Labels:

Saturday, May 25, 2013

Cross Browser Hash Change Event

hashchange adalah event JavaScript yang akan memicu suatu fungsi untuk bekerja setiap kali hash pada address bar berubah. Umumnya terjadi ketika pengguna menekan tombol Back dan/atau Forward pada peramban. Bermanfaat untuk memastikan agar AJAX bisa tetap bekerja ketika pemicu fungsi yang digunakan adalah berupa penekanan tombol Back dan Forward:

// http://stackoverflow.com/questions/9339865/get-the-hashchange-event-to-work-in-all-browsers-including-ie7
(function(w) {
    if ('onhashchange' in w) {
        if (w.addEventListener) {
            w.addHashChange = function(func, before) {
                w.addEventListener('hashchange', func, before);
            };
            w.removeHashChange = function(func) {
                w.removeEventListener('hashchange', func);
            };
            return;
        } else if (w.attachEvent) {
            w.addHashChange = function(func) {
                w.attachEvent('onhashchange', func);
            };
            w.removeHashChange = function(func) {
                w.detachEvent('onhashchange', func);
            };
            return;
        }
    }
    var hashChangeFuncs = [], oldHref = location.href;
    w.addHashChange = function(func, before) {
        if (typeof func === 'function') hashChangeFuncs[before ? 'unshift' : 'push'](func);
    };
    w.removeHashChange = function(func) {
        for (var i = hashChangeFuncs.length-1; i >= 0; i--) {
            if (hashChangeFuncs[i] === func) hashChangeFuncs.splice(i, 1);
        }
    };
    setInterval(function() {
        var newHref = location.href;
        if (oldHref !== newHref) {
            oldHref = newHref;
            for (var i = 0; i < hashChangeFuncs.length; i++) {
                hashChangeFuncs[i].call(w, {
                    'type': 'hashchange',
                    'newURL': newHref,
                    'oldURL': oldHref
                });
            }
        }
    }, 100);
})(window);

Dasar Penggunaan

Fungsi ini akan menampilkan kotak peringatan setiap kali hash berubah. Fungsi ini tidak memerlukan pemicu seperti window.onload, elem.onclick, atau event apapun! Karena pemicu kemunculan kotak pesan berasal dari perubahan hash pada peramban. Untuk mengubah hash pada peramban bisa dilakukan dengan cara mengeklik tautan lokal yang mengandung hash atau menekan tombol Back dan/atau Forward:

addHashChange(function() {
    alert('OK!');
});

Lihat Demo

Sampel Penerapan AJAX

$('.ajax-link').on("click", function() {
    window.location.hash = this.hash;
    return false;
});

// If user opens a URL that already contains a hash...
if (window.location.hash) {
    var theHash = window.location.hash; // Save the hash
    window.location.hash = ''; // Remove the hash, so if the AJAX link is clicked, the `hashchange` event will be triggered.
    $('.ajax-link').filter(function() {
        return this.hash == theHash;
    }).trigger("click"); // Trigger a click event to the AJAX link if it `hash` match with `window.location.hash`
}

// From hash change or history (Back/Forward button)
// Does not require any event. Just place the function like this...
// Because the trigger came from the hash changes in the address bar.
addHashChange(function(e) {
    var url = (e.newURL||location.href).split('#');
    $('#container').load(url[0] + ' #' + url[1]);
});

Labels: ,

Thursday, May 23, 2013

Template Blogazine 21.04.92

Pembaharuan 19 Maret 2013: Memperbaiki framework templat dengan menyusun ulang satuan-satuan elemen yang lebih fleksibel + mengaktifkan hack meta deskripsi Blogger. Saya sarankan Anda untuk mengunduh ulang/melihat ulang blog demo framework templat Blogazine ini!

Template Blogazine 21.04.92

Setelah beberapa bulan melakukan penelitian sendiri, merasakan bagaimana sulitnya membuat posting unik dan mengetahui apa yang bisa dipermudah dan apa yang membuat Saya merasa sulit untuk membuatnya, pada akhirnya Saya memutuskan untuk merilis templat blogspot khusus Blogazine yang diharapkan bisa menjadi standar:

Lihat Demo Unduh Templat

Tampilannya memang sangat sederhana, tapi justru itulah tujuan Saya. Saya membuat halaman muka templat ini polos, dan bisa dibilang tidak memiliki unsur desain sama sekali. Saya harap kalian bisa memodifikasi tampilan halaman muka sesuka hati dan menciptakan identitas kalian masing-masing. Sebagai catatan, disarankan untuk tidak menyentuh bagian-bagian kode CSS di dalam <b:skin> karena Saya sudah merancangnya agar bisa mempermudah pembuatan posting unik pada halaman item. Untuk mengedit/mendesain tampilan halaman muka, kalian bisa mencoba berkreasi pada bagian ini:

<!-- MODIFIKASI TAMPILAN HALAMAN MUKA DI SINI! -->
<style>

/* General */
body {}

/* Header */
#headace {
  text-align:right;
  padding:2em 2.5em;
}
#headace h1 {
  margin:0 0;
  font-size:400%;
}
#headace p {
  font-size:120%;
  margin:.5em 0 0;
}

/* Posts */
.post {
  margin:0 0;
  padding:0 0;
}
.post-outer {margin:0 5%}
.post .post-title {
  margin:0 0;
  font-size:120%;
  text-align:left;
}
.post-footer {margin:.5em 0 1.5em}
.date-header {display:none}

</style>

Sistem Grid

Saya menggunakan sistem grid 1140px Grid dari Andy taylor yang juga Saya gunakan dalam blog Blogazine Saya. Dengan sistem grid, kalian tidak perlu lagi membuat peraturan media queries berkali-kali pada setiap posting, karena sistem grid sudah disusun dalam satu paket di dalam templat. Berikut ini adalah konsep dasar pembuatan kolom pada posting:

Pertama-tama buat pembungkus luar berupa elemen .row:

<div class="row">
    ...
</div>

Setelah itu kalian tentukan sendiri, akan menggunakan model grid berapa kolom. Dalam sistem grid ini ada setidaknya sebelas macam ukuran. Masing-masing dibagi dalam kelas yang berbeda seperti ini:

  1. onecol untuk standar 12 kolom sama lebar
  2. twocol untuk standar 6 kolom sama lebar
  3. threecol untuk standar 4 kolom sama lebar
  4. fourcol untuk standar 3 kolom sama lebar
  5. fivecol
  6. sixcol untuk standar 2 kolom sama lebar
  7. sevencol
  8. eightcol
  9. ninecol
  10. tencol
  11. elevencol

fivecol, sevencol, eightcol, ninecol, tencol dan elevencol digunakan untuk layout kolom lanjutan. Misalnya jika kita ingin membuat dua kolom dengan lebar yang berbeda. Contoh sederhana, untuk membuat dua kolom sama lebar, kita bisa menggunakan .sixcol seperti ini:

<div class="row">
    <div class="sixcol">
        ...
    </div>
    <div class="sixcol last">
        ...
    </div>
</div>

Catatan: Jangan lupa untuk menyertakan kelas .last pada setiap akhir kolom. Itu digunakan untuk menghilangkan margin-right yang berlebih pada kolom terakhir.

Gambaran selengkapnya mengenai hasil penerapan kelas-kelas grid di atas bisa kalian lihat di halaman ini:

Lihat Demo

Perataan Gambar dan Teks

Sistem perataan gambar dan teks sudah Saya buat dalam satu paket CSS di dalam templat. Tugas kalian hanya tinggal menerapkan kelas-kelasnya saja pada elemen yang dikehendaki:

/* CSS Float */
.clear {clear:both} /* clear float */
.left {float:left} /* left alignment */
.right {float:right} /* right alignment */
.hidden {display:none} /* hidden element */
.visually-hidden {
  position:absolute !important;
  top:-9999px;
  left:-9999px;
} /* accessible hidden element */

/* Text Alignment */
.text-left {text-align:left} /* text-align left */
.text-right {text-align:right} /* text-align right */
.text-center {text-align:center} /* text-align center */

/* Image Alignment */
img.left {margin:0 1em .2em 0} /* left alignment */
img.right {margin:0 0 .2em 1em} /* right alignment */
img.center {margin:0 auto} /* center alignment */

Sebagai contoh, jika kalian ingin menerapkan perataan gambar ke samping kiri, tambahkan kelas left seperti ini:

<img class="left" src="gambar.jpg" alt="" />

Sisanya perataan kanan dan tengah Saya rasa bisa dengan mudah dipahami:

<img class="right" src="gambar.jpg" alt="" />
<img class="center" src="gambar.jpg" alt="" />

Editor Blogger biasanya akan menyisipkan elemen .separator pada setiap gambar yang berhasil diunggah. Jadi, dibandingkan menerapkan kelas pada gambar secara langsung, Saya lebih menyarankan kalian untuk menerapkan kelas perataan pada elemen .separator seperti ini:

<div class="separator center">
    <a href="#"><img src="gambar.jpg" alt="" /></a>
</div>
<div class="separator left">
    <a href="#"><img src="gambar.jpg" alt="" /></a>
</div>
<div class="separator right">
    <a href="#"><img src="gambar.jpg" alt="" /></a>
</div>

Hapus semua inline-style bawaan dari editor Blogger (Misalnya: style="margin-left:1em;margin-right:1em;"). Kita cukup menggunakan kelas perataan pada setiap elemen.

Perataan teks tidak sulit, cukup buat elemen baru kemudian tambahkan kelas perataan, atau tentukan elemen mana yang ingin diberi kelas perataan:

<div class="text-right"> ... </div>
<div class="row">
    <div class="fourcol text-right">
        ...
    </div>
    <div class="fourcol text-center">
        ...
    </div>
    <div class="fourcol last">
        ...
    </div>
</div>

Lihat Demo

Lainnya

Formulir komentar tersembunyi dan fitur thread-commenting bawaan Blogger siap pakai.

Lisensi

http://creativecommons.org/licenses/by/2.5/ - Artinya bahwa Anda boleh mengubah nama pembuat, mengubah identitas templat dan footer namun dengan syarat tetap mempertahankan keterangan sumber. Tidak perlu repot-repot membuat tautan aktif yang dipasang di catatan kaki blog, cukup biarkan semua atribusi yang ada di dalam kode. Selebihnya terserah Anda: Tidak ada lisensi/tidak mewajibkan atribusi, kecuali sistem grid, kalau mau.

Unduh Templat

Labels:

Framework CSS · Utamakan Konsistensi Tampilan Artikel Sebelum Layout

CSS Framework

Yang Saya maksudkan di sini adalah, jadikan tampilan artikel sebagai prioritas utama sebelum memulai pondasi desain/rancangan tema/template. Mengingat kebiasaan buruk yang sering terjadi adalah kita membentuk hasil jadinya terlebih dahulu kemudian baru merancang tampilan-tampilan paragraf, kuota dan blok kode. Padahal, dengan merancang elemen-elemen kecil dan umum tersebut terlebih dahulu, kita bisa memastikan bahwa tampilan akhir nantinya akan menjadi lebih konsisten.

Merancang penampilan secara keseluruhan dan melanjutkannya dengan merancang tampilan elemen artikel hanya akan menambah waktu kerja kita menjadi dua kali lipat lebih lama dan lebih rumit tanpa kita sadari. Sebagai contoh, saat kita merancang tampilan posting, saat itu kita juga akan menentukan tampilan judulnya. Setelah itu kita akan merancang tampilan sidebar dan footer, kemudian juga akan menentukan tampilan judulnya dan seterusnya:

Contoh Buruk

/* posting */
.post {
  font-family:Arial,Sans-Serif;
  font-size:12px;
  color:#333;
}

.post h2 {
  font-size:30px;
  font-weight:bold;
  margin-bottom:15px;
  color:#3399ff;
}

/* sidebar */
.sidebar {
  float:right;
  width:200px;
  overflow:hidden;
  word-wrap:break-word;
  font-family:Arial,Sans-Serif;
  color:#222;
}

.sidebar h2 {
  font-weight:normal;
  font-size:12px;
  text-transform:uppercase;
  margin-bottom:15px;
}

/* footer */
.footer {
  background-color:#2f2f2f;
  font-family:Georgia,Serif;
  font-size:13px;
  color:#666;
}

.footer h2 {
  font-weight:normal;
  font-size:20px;
  color:#f5f5f5;
}

Terlalu banyak pekerjaan hanya untuk membuat beberapa blok area saja. Seharusnya pekerjaan ini bisa menjadi lebih singkat apabila kita merancang framework elemen-elemen artikel terlebih dahulu secara global. Sudah ada beberapa framework yang tersedia untuk mengatasi kebiasaan buruk ini, misalnya Normalize dan HTML5 Boilerplate. Tapi di sini kita akan mencoba untuk membuatnya sendiri. Dimulai dengan CSS reset.

Merancang Framework CSS

CSS Reset

CSS ini akan menormalkan semua tampilan elemen HTML —kecuali elemen-elemen formulir— menjadi seragam/normal. Dimulai dari ukuran, warna, margin, padding, dimensi dan juga ketebalannya. Mengawali rancangan elemen artikel dengan CSS reset akan mempermudah kita dalam merancang tampilan elemen-elemen HTML setelah ini:

/* 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;
}

Elemen <BODY>

Berikutnya kita atur ukuran huruf, tipe huruf, line-height dan warna huruf secara global pada elemen <body>:

body {
  /* `font-style:normal`,
     `font-weight:normal`,
     `font-size:13px`,
     `line-height:1.4em`,
     `font-family:Arial,Sans-Serif` */
  font:normal normal .8125em/1.4 Arial,Sans-Serif;
  background-color:white; /* warna latar secara global */
  color:#333; /* warna huruf secara global */
}

Huruf Tebal, Huruf Miring dan Elemen-Elemen Kecil Lainnya

Karena tampilan elemen HTML sudah diatur ulang oleh CSS reset, maka kita perlu mengatur beberapa tampilan elemen menjadi seperti semula:

/* huruf tebal */
strong,b {
  font-weight:bold;
}

/* citation & huruf miring (italic + emphasis) */
cite,em,i {
  font-style:italic;
}

/* tautan */
a {
  text-decoration:none;
}

a:hover {
  text-decoration:underline;
}

/* Internet Explorer akan menambahkan border pada gambar
   yang diliputi oleh tautan */
a img {
  border:none;
}

/* abbreviation & acronym */
abbr,
acronym {
  border-bottom:1px dotted;
  cursor:help;
}

/* superscript & subscript */
sup,
sub {
  vertical-align:baseline;
  position:relative;
  top:-.4em;
  font-size:86%;
}

sub {
  top:.4em;
}

/* huruf kecil */
small {
  font-size:86%;
}

/* tombol keyboard */
kbd {
  font-size:80%;
  border:1px solid #999;
  padding:2px 5px;
  border-bottom-width:2px;
  border-radius:3px;
}

/* penanda teks */
mark {
  background-color:#ffce00;
  color:black;
}

Margin Paragraf

Paragraf membutuhkan kerenggangan antara teks paragraf yang satu dengan yang lainnya. Begitu pula elemen-elemen lain yang biasa menyertainya seperti kuota, tabel, figur, formulir, daftar dan blok kode:

p,blockquote,pre,
table,figure,hr,form,
ol,ul,dl {
  margin:1.5em 0;
}

Elemen Heading

Atur elemen heading dengan line-height menjadi normal dan huruf menjadi tebal. Tentukan juga margin heading secara global sebelum kemudian kita melanjutkannya dengan menentukan ukuran elemen heading sesuai dengan level/tingkatannya:

h1,h2,h3,h4,h5,h6 {
  font-weight:bold;
  line-height:normal;
  margin:1.5em 0 0;
}

h1 {font-size:200%}
h2 {font-size:180%}
h3 {font-size:160%}
h4 {font-size:140%}
h5 {font-size:120%}
h6 {font-size:100%}

Elemen Daftar

Jangan biarkan elemen daftar menjadi terlalu sejajar dengan paragraf karena pada umumnya itu hanya akan membuat mata kita menjadi merasa tidak nyaman dan tertekan. Posisikan elemen daftar menjadi sedikit menjorok ke depan untuk menciptakan kesan istirahat/fokus:

/* ordered, unordered list & description list */
ol,ul,dl {margin-left:3em}

ol {list-style:decimal outside} /* atur ulang `list-style` pada elemen `<ol>` */
ul {list-style:disc outside} /* atur ulang `list-style` pada elemen `<ul>` */
li {margin:.5em 0} /* beri sedikit jarak atas dan bawah pada elemen `<li>` untuk item daftar dengan konten yang panjang */

dt {font-weight:bold}
dd {margin:0 0 .5em 2em}

Elemen Formulir

Biasanya ini tidak terlalu penting. Tetapi setidaknya samakanlah tipe dan ukuran huruf sesuai dengan huruf pada elemen induknya. Mengenai tampilan selanjutnya seperti warna latar dan efek :hover bisa ditentukan nanti setelah framework selesai dibuat:

input,
button,
select,
textarea {
  font:inherit;
  font-size:100%;
  line-height:normal;
  vertical-align:baseline;
}

/* mengeset `box-sizing` menjadi `border-box` pada `<textarea>` untuk mengatasi masalah
   pengguna yang sering kesulitan menentukan lebar akurat
   pada elemen ini menjadi `100%` ketika menggunakan logika box-model yang lama */
textarea {
  display:block;
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
}

Blok Kode dan Kuota

<pre> dan <blockquote> biasanya mendapatkan perlakuan khusus mengingat elemen ini biasa kita gunakan untuk menyatakan hal-hal yang penting. Blok kode digunakan untuk menyatakan kode yang perlu dicatat/dipahami dan kuota digunakan untuk menyatakan teks yang perlu diingat atau direnungkan:

pre,
code {
  font-family:"Courier New",Courier,Monospace;
  color:inherit;
}

/* jika perlu tentukan juga warna latar dan huruf */
pre {
  white-space:pre;
  word-wrap:normal;
  overflow:auto;
}

blockquote {
  margin-left:2em;
  margin-right:2em;
  border-left:4px solid #ccc;
  padding-left:1em;
  font-style:italic;
}

Tabel

Seperti yang pernah Saya nyatakan pada tutorial pembuatan tabel dengan HTML, disarankan untuk menentukan border dan padding pada tabel yang memiliki atribut border=1 saja demi keamanan:

table[border="1"] th,
table[border="1"] td,
table[border="1"] caption {
  border:1px solid;
  padding:.5em 1em;
  text-align:left;
  vertical-align:top;
}

th {
  font-weight:bold;
}

table[border="1"] caption {
  border:none;
  font-style:italic;
}

Hasil Akhir

/* 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;
}

/* ===============
   FRAMEWORK START
   =============== */
body {
  font:normal normal .8125em/1.4 Arial,Sans-Serif;
  background-color:white;
  color:#333;
}

strong,b {
  font-weight:bold;
}

cite,em,i {
  font-style:italic;
}

a {
  text-decoration:none;
}

a:hover {
  text-decoration:underline;
}

a img {
  border:none;
}

abbr,
acronym {
  border-bottom:1px dotted;
  cursor:help;
}

sup,
sub {
  vertical-align:baseline;
  position:relative;
  top:-.4em;
  font-size:86%;
}

sub {
  top:.4em;
}

small {
  font-size:86%;
}

kbd {
  font-size:80%;
  border:1px solid #999;
  padding:2px 5px;
  border-bottom-width:2px;
  border-radius:3px;
}

mark {
  background-color:#ffce00;
  color:black;
}

p,blockquote,pre,
table,figure,hr,form,
ol,ul,dl {
  margin:1.5em 0;
}

hr {
  height:1px;
  border:none;
  background-color:#666;
}

h1,h2,h3,h4,h5,h6 {
  font-weight:bold;
  line-height:normal;
  margin:1.5em 0 0;
}

h1 {font-size:200%}
h2 {font-size:180%}
h3 {font-size:160%}
h4 {font-size:140%}
h5 {font-size:120%}
h6 {font-size:100%}

ol,ul,dl {margin-left:3em}
ol {list-style:decimal outside}
ul {list-style:disc outside}
li {margin:.5em 0}

dt {font-weight:bold}
dd {margin:0 0 .5em 2em}

input,
button,
select,
textarea {
  font:inherit;
  font-size:100%;
  line-height:normal;
  vertical-align:baseline;
}

textarea {
  display:block;
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
}

pre,
code {
  font-family:"Courier New",Courier,Monospace;
  color:inherit;
}

pre {
  white-space:pre;
  word-wrap:normal;
  overflow:auto;
}

blockquote {
  margin-left:2em;
  margin-right:2em;
  border-left:4px solid #ccc;
  padding-left:1em;
  font-style:italic;
}

table[border="1"] th,
table[border="1"] td,
table[border="1"] caption {
  border:1px solid;
  padding:.5em 1em;
  text-align:left;
  vertical-align:top;
}

th {
  font-weight:bold;
}

table[border="1"] caption {
  border:none;
  font-style:italic;
}

Sampai di sini Saya rasa sudah cukup untuk dijadikan sebagai dasar. Setelah ini Anda bisa melanjutkan untuk membuat kelas-kelas produktif seperti .hidden, .visually-hidden, .btn dan yang lainnya untuk keperluan rancangan tingkat lanjut:

.hidden,[hidden] {
  display:none;
}

.invisible {
  visibility:hidden;
}

.visually-hidden {
  position:absolute !important;
  overflow:hidden;
  clip:rect(0px 0px 0px 0px);
  clip:rect(0px,0px,0px,0px);
  height:1px;
  width:1px;
  margin:-1px 0 0;
  padding:0;
  border:0;
}

.clear {
  display:block;
  clear:both;
}

.clearfix:before,
.clearfix:after {
  content:"";
  display:table;
}

.clearfix:after {
  clear:both;
}

.clearfix {
  *zoom:1;
}

.pull-left {
  float:left;
}

.pull-right {
  float:right;
}

.centered {
  clear:both;
  display:block;
  text-align:center;
  margin-left:auto;
  margin-right:auto;
}

.text-center {
  text-align:center;
}

.text-left {
  text-align:left;
}

.text-right {
  text-align:right;
}

.text-justify {
  text-align:justify;
}

.btn {
  color:white;
  background-color:black;
  /* ... */
}

.btn:hover {
  /* ... */
}

.btn:active {
  /* ... */
}

Beberapa nama kelas di atas akan sangat mudah Anda temui pada framework HTML5 Boilerplate dan Twitter Bootstrap (Twitter Bootstrap juga memakai HTML5 Boilerplate). Anda akan mengetahui fungsi-fungsi kelas tersebut, mengapa kelas tersebut dibuat dan mengapa kelas-kelas tersebut menjadi semacam “standar” saat Anda mempelajarinya.

Beralih ke Framework Buatan Sendiri

Untuk mempercepat pekerjaan, yang terpenting sebenarnya adalah framework. Namun jika Anda tidak mengerti apa dan bagaimana framework itu dibuat dan digunakan, maka hasil akhirnya nanti akan sama saja. Memulai membuat framework sendiri Saya pikir jauh lebih baik dibandingkan hanya sekedar menyalin dan menempel kode dari framework lain yang sudah ada. Mengikuti dan mempelajari bagaimana mereka menciptakan framework seharusnya lebih diutamakan dibandingkan hanya sekedar memakainya. Karena dengan mempelajari bagaimana sebuah framework terbentuk, maka dari situ Anda bisa lebih cerdas di dalam mencontoh dan menyaring apa-apa saja yang sebenarnya diperlukan dan apa saja yang sebenarnya tidak diperlukan menurut kebutuhan Anda saat itu untuk keperluan yang lebih spesifik dan efisien tentunya:

Lihat Demo

Labels: , , ,

Wednesday, May 22, 2013

Jangan Mendeklarasikan `font-weight` dan `font-style` pada Font yang Tidak Memiliki Varian Tersebut

Membandingkan tampilan font Open Sans dengan varian regular saja dan font Open Sans dengan varian yang lengkap.

Ada satu hal yang mungkin tidak Anda sadari bahwa ketika Anda menyatakan font-family pada teks, maka peramban akan mencoba untuk menciptakan efek bold dan italic palsu ketika peramban tidak berhasil menemukan file font bold dan italic pada font terkait. Sebagai contoh, Tahoma hanya memiliki dua varian, yaitu regular dan bold, sehingga hasil tampilan teks pada peramban hanya akan terlihat bagus pada model teks biasa dan tebal:

Tahoma Fonts Preview
Tahoma

Karena sejak awal varian italic tidak pernah ada pada keluarga font Tahoma, maka peramban mencoba untuk merekayasa dimensi font tersebut menjadi italic. Akan tetapi tetap saja, efek italic yang Anda lihat bukanlah italic yang sesungguhnya. Perbedaan akan terlihat jelas pada jenis-jenis font yang memiliki lebih banyak varian. Misalnya Georgia:

Georgia Fonts
Georgia

Georgia memiliki empat varian, termasuk di dalamnya adalah regular, italic, bold bahkan bold-italic. Hal ini memungkinkan peramban untuk menampilkan dimensi font dalam “porsi” yang tepat pada varian font minimal. Yaitu regular, italic, bold dan bold-italic:

Georgia Fonts
Georgia

Hal Buruk yang Sering Saya Lihat

Hal buruk yang sering Saya lihat adalah bahwa seorang pengguna mencoba untuk menyatakan font-weight:bold atau font-style:italic pada keluarga font yang tidak memiliki varian tersebut atau pada keluarga font yang memiliki varian tersebut, akan tetapi varian selain regular tidak pernah disertakan di dalam deklarasi @font-face:

Bebas Neue with Fake Bold EffectBebas Neue with Regular Weight
Gambar 1: Mendeklarasikan ketebalan font heading pada situasi yang salah. Gambar 2: Dimensi font yang sesungguhnya.Keterangan: Bebas Neue pada judul dan Franklin Gothic Medium pada paragraf.

Pada keadaan normal, elemen heading akan memiliki efek tebal secara otomatis. Jadi, jangan lupa untuk mendeklarasikan font-weight dan font-style dengan nilai normal saat Anda sedang menerapkan font kustom yang tidak memiliki varian lengkap untuk elemen ini:

h1,h2,h3,h4,h5,h6 {
  font-family:"Bebas Neue",Sans-Serif;
  font-style:normal;
  font-weight:normal;
}

Mencari tutorial tentang cara menggunakan @font-face, baca di artikel Menggunakan @font-face

Labels: , ,

Sunday, May 5, 2013

Tes Dukungan CSS Transisi pada Peramban

// http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr/13081497#13081497
var supportCSSTransitions = (function() {
    var s = document.createElement('p').style;
    return 'transition' in s ||
           'WebkitTransition' in s ||
           'MozTransition' in s ||
           'msTransition' in s ||
           'OTransition' in s;
})();

Penggunaan

Menambahkan kelas spesifik pada tag <html> berdasarkan dukungan CSS transisi pada peramban yang dipakai:

document.documentElement.className +=
    supportCSSTransitions ? " css-transition" : " no-css-transition";

Menggunakan animasi CSS transisi untuk performa yang lebih baik jika peramban yang dipakai mendukung CSS transisi, dan akan dialihkan ke jQuery .animate() jika peramban yang dipakai tidak mendukung CSS transisi:

if (supportCSSTransitions) {
    $('div').css({
        "top": 50,
        "left": 100
    });
} else {
    $('div').animate({
        "top": 50,
        "left": 100
    }, 1000);
}

Labels: ,

Friday, May 3, 2013

Jalan Pintas untuk Menangani Perintah-Perintah JQuery di dalam Peraturan Kondisi

Dalam sebuah forum Saya pernah sekali diajari mengenai cara tersingkat untuk menangani perintah-perintah jQuery di dalam peraturan kondisi yang biasa dituliskan seperti ini:

if (statement) {
    $(selector).method1();
} else {
    $(selector).method2();
}

Kode di bawah ini adalah jalan pintas untuk kondisional di atas:

$(selector)[statement ? "method1" : "method2"]();

Pada awalnya Saya merasa bingung dengan sudut pandang yang orang tersebut berikan, sampai kemudian Saya menyadari bahwa pada dasarnya ini hanyalah sebuah jalan pintas peraturan if/else untuk memanggil item objek yang berbeda berdasarkan kondisi tertentu.

jQuery, pada dasarnya hanyalah sekumpulan fungsi yang dinyatakan di dalam objek. Kurang lebihnya seperti ini (memang tidak sama persis seperti ini, tapi setidaknya lumayan mirip):

var foo = {
    addClass: function(param) { ... },
    removeClass: function(param) { ... },
    toggleClass: function(param) { ... },
    hasClass: function(param) { ... }
    ...
}

Sehingga setiap fungsi bisa dipanggil dengan cara seperti ini:

foo.addClass('bar');
foo.removeClass('bar');

Atau seperti ini:

foo["addClass"]('bar');
foo["removeClass"]('bar');

Katakanlah kita ingin memanggil fungsi tertentu di dalam foo hanya jika suatu kondisi terpenuhi. Jika kondisi tidak terpenuhi, maka fungsi cadangan yang lain akan dijalankan:

if (abc === true) {
    foo["removeClass"]('bar');
} else {
    foo["addClass"]('bar');
}

Yang mana jika diubah ke pernyataan kondisional ringkas akan menjadi seperti ini:

var x = (abc === true) ? "removeClass" : "addClass";
foo[x]('bar');

Sehingga kita bisa menyimpulkannya menjadi seperti ini:

foo[abc === true ? "removeClass" : "addClass"]('bar');

Contoh Penerapan

Berikut ini adalah contoh penerapan kondisional jalan pintas untuk menangani perintah .slideDown() dan .fadeOut() berdasarkan visibilitas panel:

Sebelum

$('h2').click(function() {
    $(this).toggleClass('active');
    if ($(this).next().is(':hidden')) {
        $(this).next().slideDown();
    } else {
        $(this).next().fadeOut();
    }
});

Sesudah

$('h2').click(function() {
    $(this).toggleClass('active')
        .next()[$(this).next().is(':hidden') ? "slideDown" : "fadeOut"]();
});

Lihat Demo

Labels: , , ,