Header Ads

CODEFLARE ADVERTISING
OPEN AD SPACE
Pasang Iklan di CodeFlare
Promosikan bisnis, produk, website atau layanan Anda.
SLOT TERSEDIA
PASANG IKLAN
  • Widget Retro Digital Feed Blogger dengan Model Scanline Futuristik

    Widget Retro Digital Feed Blogger Responsive dengan Efek Model Scanline


    Waktu membuat area artikel terbaru di Blogger, saya tidak ingin hasilnya cuma berupa daftar judul dan thumbnail yang terasa datar. Saya ingin feed tetap ringan dan mudah dipakai, tapi punya karakter visual yang langsung terlihat berbeda. Dari situ saya membuat Widget Retro Digital Feed Blogger: enam artikel terbaru yang dibagi menjadi tiga card di kiri, model transparan di tengah, dan tiga card di kanan, lengkap dengan perspektif lembut, loading skeleton, digital reveal, serta scanner tipis yang mengikuti siluet model.

    Saya membuat widget ini supaya tetap praktis dipasang lewat gadget HTML/JavaScript Blogger. Feed, thumbnail, loading model, scanner, dan tampilan responsif sudah berada dalam satu paket kode, jadi pengguna tidak perlu menyusun komponennya satu per satu. Di artikel ini saya membahas cara kerjanya, manfaatnya, bagian yang bisa dikustomisasi, dan langkah pemasangannya dengan cara yang mudah diikuti.

    Informasi Singkat
    Platform: Blogger / Blogspot
    Tipe: Widget feed artikel terbaru
    Jumlah artikel: 6
    Layout: 3 kiri + model tengah + 3 kanan
    Feed: Blogger JSONP
    Domain feed: otomatis mengikuti blog aktif
    Thumbnail: adaptive s128 / s256 / s320 / s640 / s800
    Model: PNG/WebP transparan
    JavaScript: Native JS
    Responsive: Ya

    Apa Itu Widget Retro Digital Feed Blogger?

    Widget ini pada dasarnya adalah recent posts Blogger yang saya kemas dengan tampilan berbeda. Tiga artikel muncul di sisi kiri, sebuah model transparan berada di tengah, lalu tiga artikel berikutnya tampil di sisi kanan. Saya sengaja membiarkan setiap card berdiri sendiri tanpa panel besar supaya tampilannya terasa lebih ringan dan tidak menutupi background retro digital.

    Untuk latarnya saya memakai kombinasi gradient ungu gelap, garis horizon terang, grid perspektif, dan aura lembut di tengah. Saya tidak ingin efeknya terlalu ramai, jadi card dibuat dengan warna biru gelap transparan, aksen digital tipis, glow halus, dan zoom kecil pada thumbnail ketika disentuh mouse.

    ARTICLE 01ARTICLE 02ARTICLE 03
    MODELSCANLINE
    ARTICLE 04ARTICLE 05ARTICLE 06

    Konsep Tampilan 3 Artikel Kiri, Model Tengah, 3 Artikel Kanan

    Saya membagi feed menjadi dua kelompok. Tiga post pertama masuk ke .cfStaticLeftItems, lalu tiga post berikutnya masuk ke .cfStaticRightItems. Kedua sisi saya beri perspektif yang berlawanan supaya susunan card terasa sedikit menghadap ke model di tengah.

    Untuk hover saya memilih gerakan yang sederhana. Card kiri bergeser sedikit ke kanan dan naik tipis, sedangkan card kanan bergerak ke arah sebaliknya. Border dan glow ikut menguat sedikit, sementara thumbnail hanya melakukan zoom ringan. Menurut saya efek seperti ini lebih enak dilihat karena tetap memberi respons visual tanpa membuat judul artikel sulit dibaca.

    Fungsi Widget

    Recent Posts BloggerMenampilkan enam artikel terbaru dari feed blog aktif.
    Feed DinamisTidak perlu mengisi domain Blogger secara manual.
    Adaptive ThumbnailUkuran gambar dipilih berdasarkan lebar card.
    Loading SkeletonSlot artikel tetap terlihat rapi sebelum feed selesai.
    Model ScanlineModel memiliki INITIALIZING MODEL, reveal, dan scanner.
    ResponsivePerspective, ukuran card, dan model menyesuaikan layar kecil.

    Feed Dinamis Berdasarkan Domain Tempat Widget Dipasang

    Salah satu hal yang paling saya suka dari widget ini adalah saya tidak perlu menulis alamat blog secara manual. Script membaca domain aktif melalui location.origin. Kalau nilai itu tidak tersedia, script memakai kombinasi protocol dan host sebagai cadangan.

    Setelah domain terbaca, script membentuk endpoint /feeds/posts/default?alt=json-in-script. Karena itu kode yang sama bisa saya pindahkan dari alamat Blogspot ke custom domain, atau dipakai di blog Blogger lain, tanpa sibuk mengganti hostname di JavaScript.

    Feed mengikuti domain aktif.
    Tidak perlu mengganti URL blog ketika widget dipasang di domain lain. Cukup tempel kode utuh ke gadget HTML/JavaScript.

    Kenapa Menggunakan Blogger JSONP Feed?

    Untuk mengambil artikel saya memakai feed Blogger dengan format alt=json-in-script. Cara ini memungkinkan data dibaca lewat JSONP. Script membuat callback unik, memasukkannya ke URL feed, lalu menunggu Blogger mengembalikan data artikel.

    Begitu feed selesai dimuat, data diproses dan enam artikel langsung dirender ke card kiri dan kanan. Setelah itu callback serta elemen script sementara dibersihkan lagi. Kalau feed gagal dimuat, saya memilih cukup menulis peringatan di Console browser supaya pengunjung tidak melihat pesan error mentah di area widget.

    Adaptive Thumbnail untuk Blogger, CodeFlare, dan GitHub

    Untuk thumbnail saya tidak hanya mengandalkan satu sumber. Engine lebih dulu mencoba membaca gambar dari content artikel, kemudian summary, lalu memakai media$thumbnail jika memang diperlukan. Ini membantu terutama saat Blogger memakai feed pendek dan posisi gambar di feed tidak selalu sama.

    Setelah gambar ditemukan, script menyesuaikan pola URL Blogger dan CodeFlare seperti folder /s256/, /s320/, /s640/, format =s..., atau /w640-h360/. Untuk gambar dari GitHub, URL tampilan github.com/.../blob/... dan github.com/.../raw/... diarahkan ke raw.githubusercontent.com agar file gambar bisa dipakai langsung.

    Ukuran gambar lalu dipilih berdasarkan lebar card. Kalau ruangnya kecil, saya cukup memakai s128 atau s256. Saat card lebih lebar, engine bisa naik ke s320, s640, atau s800. Untuk gambar CodeFlare, source utama tetap dijaga supaya kalau versi ukuran yang diuji tidak tersedia, widget masih punya gambar cadangan yang aman.

    Loading Skeleton

    Saat feed belum selesai dimuat, saya tidak membiarkan area kiri dan kanan kosong. Enam skeleton langsung muncul lebih dulu, masing-masing tiga di setiap sisi. Ada efek cahaya tipis yang bergerak supaya pengunjung tahu bahwa artikel sedang dimuat.

    Begitu data feed diterima, skeleton otomatis diganti dengan card artikel. Kalau jumlah artikel yang tersedia belum cukup, area yang tidak mendapatkan data akan menampilkan NO POSTS.

    INITIALIZING MODEL dan Loading Model

    Bagian model saya beri proses loading sendiri. Sebelum gambarnya benar-benar siap, area tengah menampilkan INITIALIZING MODEL, spinner kecil, dan progress bar tipis. Setelah gambar selesai dimuat, fungsi ready() berjalan dan class cfModelReady ditambahkan untuk memulai efek reveal.

    Kalau URL model bermasalah, tulisan loading akan berubah menjadi MODEL UNAVAILABLE. Saya sengaja memisahkan proses model dari feed artikel, jadi kegagalan gambar model tidak ikut mematikan daftar artikel.

    Perhitungan Rasio Natural Agar Model Tidak Gepeng

    Ada satu bagian yang saya sarankan jangan diubah, yaitu perhitungan rasio gambar. Setelah model selesai dimuat, script membaca naturalWidth dan naturalHeight, lalu menghitung:

    naturalWidth / naturalHeight

    Nilai itu kemudian dikalikan dengan tinggi area model dan dimasukkan ke CSS variable --cf-model-width. Dengan cara ini saya tidak perlu menebak lebar gambar secara manual, dan bentuk model tetap mengikuti proporsi aslinya.

    Digital Reveal

    Begitu cfModelReady aktif, model tidak langsung muncul begitu saja. Saya membuatnya naik dari bawah dengan kombinasi clip-path, blur, brightness, opacity, translateY, dan scale. Flash horizontal tipis ikut bergerak selama proses ini supaya kemunculannya terasa seperti proses digital boot-up.

    Scanner Tipis yang Mengikuti Siluet Model

    Bagian scanner saya buat sedikit berbeda dari garis neon biasa. Saya memakai gambar yang sama pada .cfStaticModelMain dan .cfStaticModelScan, lalu layer kedua diberi filter dan clip-path yang bergerak dari atas ke bawah dan kembali lagi.

    Karena layer scan memakai file transparan yang sama, cahaya hanya terlihat pada bagian siluet model. Efeknya jadi lebih menyatu dan tidak terlihat seperti satu garis neon panjang yang sekadar lewat di depan gambar.

    Responsive Desktop dan Mobile

    Saya juga menyiapkan breakpoint untuk layar 600 px, 420 px, dan 320 px. Saat ruang mengecil, lebar feed, perspektif, zona model, tinggi card, thumbnail, dan ukuran teks ikut menyesuaikan.

    Saya tetap mempertahankan susunan enam artikel, jadi widget paling nyaman dipasang di area yang cukup lebar seperti bawah header, section homepage, sebelum footer, atau blok HTML lebar. Di sidebar yang terlalu sempit widget masih bisa mengecil, tetapi ruang untuk model dan card tentu menjadi jauh lebih terbatas.

    Cara Memasang Widget di Blogger

    Saya memasang widget ini lewat gadget HTML/JavaScript karena itu cara paling aman dan paling mudah di Blogger. Hindari menempelkan script ke editor Compose posting karena editor artikel bisa memproses atau membuang bagian JavaScript.

    STEP 01
    Blogger Dashboard
    Postingan Statistik Komentar TATA LETAK ← pilih Tema

    STEP 01: buka Blogger Dashboard, pilih blog yang akan dipasangi widget, lalu masuk ke menu Tata Letak.

    STEP 02
    HEADER
    MAIN
    SIDEBAR

    STEP 02: pilih area layout yang cukup lebar lalu klik + Tambahkan Gadget. Posisi gadget bisa dipindahkan lagi melalui drag-and-drop di halaman Tata Letak.

    STEP 03
    Pilih Gadget HTML/JavaScript Teks Gambar Daftar Link

    STEP 03: pilih gadget HTML/JavaScript. Jangan menggunakan gadget Teks karena widget membutuhkan script untuk membaca feed.

    STEP 04
    <div class="cfStaticFeed"...>
    ...
    <style>...</style>
    <script>...</script>

    STEP 04: tempel seluruh kode widget dari baris pertama sampai baris terakhir. HTML, CSS, dan JavaScript harus ikut. Jangan hanya mengambil bagian style atau script.

    STEP 05
    ARTICLEARTICLEARTICLE
    MODEL
    ARTICLEARTICLEARTICLE

    STEP 05: klik Simpan, buka blog, lalu cek hasilnya. Tidak perlu menulis domain blog secara manual karena feed mengikuti domain tempat gadget dijalankan.

    Kode Widget Retro Digital Feed Blogger

    Di bawah ini saya sertakan kode widget lengkap. Salin semuanya dari awal sampai akhir supaya HTML, CSS, feed engine, adaptive image, loading model, dan scanner tetap bekerja sebagai satu kesatuan.

    <div class="cfStaticFeed" data-cf-static-feed> <div class="cfStaticScene"><div class="cfStaticSky"></div><div class="cfStaticHorizon"></div><div class="cfStaticFloor"></div><div class="cfStaticAura"></div></div> <div class="cfFeedSide cfFeedSideL"> <div class="cfStaticItems cfStaticLeftItems"> <div class="cfFeedSkeleton"></div><div class="cfFeedSkeleton"></div><div class="cfFeedSkeleton"></div> </div> </div> <div class="cfStaticModelZone"> <div class="cfModelLoading"> <div class="cfModelLoadBox"><span class="cfModelLoadIcon"></span><b>INITIALIZING MODEL</b><span class="cfModelLoadBar"><i></i></span></div> </div> <div class="cfStaticModelWrap"> <img class="cfStaticModel cfStaticModelMain" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm32oojC_kZi4beS7YP_I2XESQtAxSAbzvytLBZuAvAgtpuQ8PDFfCjVH595RO45FIEnwaadrH3uyobW2qi77CLjpWm-5FH0hT-LIxlS7ufkSUhxDsscfLE2DP6R0EIqdEEw4lro0oZAyboC14-Jn6PwGrqQvZmrB24VeXLpLSPH_RtAqCFJOOt8-Q8Uut/s400/loadinggo.png" alt="Model" decoding="async" fetchpriority="high"/> <img class="cfStaticModel cfStaticModelScan" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm32oojC_kZi4beS7YP_I2XESQtAxSAbzvytLBZuAvAgtpuQ8PDFfCjVH595RO45FIEnwaadrH3uyobW2qi77CLjpWm-5FH0hT-LIxlS7ufkSUhxDsscfLE2DP6R0EIqdEEw4lro0oZAyboC14-Jn6PwGrqQvZmrB24VeXLpLSPH_RtAqCFJOOt8-Q8Uut/s400/loadinggo.png" alt="" aria-hidden="true"/> <span class="cfModelRevealFlash"></span> </div> </div> <div class="cfFeedSide cfFeedSideR"> <div class="cfStaticItems cfStaticRightItems"> <div class="cfFeedSkeleton"></div><div class="cfFeedSkeleton"></div><div class="cfFeedSkeleton"></div> </div> </div> </div> <style> .cfStaticFeed{position:relative;width:100%;height:320px;margin:0;overflow:hidden;border-radius:18px;background:#060217;border:1px solid rgba(118,95,225,.28);box-shadow:0 14px 30px rgba(0,0,0,.28);font:15px/1.35 Roboto,Arial,sans-serif}.cfStaticFeed *{box-sizing:border-box} /* BG */ .cfStaticScene{position:absolute;inset:0;z-index:0;overflow:hidden;background:#08051d;pointer-events:none}.cfStaticSky{position:absolute;inset:0 0 36%;background:radial-gradient(ellipse at 50% 100%,rgba(153,0,255,.3),transparent 58%),linear-gradient(180deg,#121029 0%,#251039 32%,#48096f 70%,#7814bd 100%)}.cfStaticHorizon{position:absolute;z-index:3;left:0;right:0;top:63%;height:3px;background:#d9ffff;box-shadow:0 0 4px #fff,0 0 8px #48eaff,0 0 16px #14cbff,0 0 28px rgba(0,199,255,.82)}.cfStaticFloor{position:absolute;z-index:1;left:-25%;right:-25%;bottom:-35%;height:73%;background-color:#060318;background-image:linear-gradient(rgba(233,45,255,.88) 1px,transparent 1px),linear-gradient(90deg,rgba(177,42,255,.9) 1px,transparent 1px);background-size:24px 15px;transform:perspective(215px) rotateX(55deg);transform-origin:50% 0}.cfStaticAura{position:absolute;left:50%;top:49%;z-index:2;width:180px;height:180px;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(circle,rgba(79,228,255,.14),rgba(167,33,255,.08) 50%,transparent 75%);filter:blur(10px)} /* FLOATING FEED */ .cfFeedSide{position:absolute;top:50%;z-index:10;width:30%;height:292px;transform-style:preserve-3d} .cfFeedSideL{left:2%;transform:translateY(-50%) perspective(900px) rotateY(17deg);transform-origin:left center} .cfFeedSideR{right:2%;transform:translateY(-50%) perspective(900px) rotateY(-17deg);transform-origin:right center} .cfStaticItems{display:flex;width:100%;height:100%;flex-direction:column;justify-content:space-between} /* RETRO DIGITAL CARD */ .cfStaticCard,.cfFeedSkeleton{position:relative;display:block;width:100%;height:91px;padding:5px;overflow:hidden;background:linear-gradient(180deg,rgba(8,22,41,.82),rgba(6,14,29,.72));border:1px solid rgba(87,186,224,.25);border-radius:6px;box-shadow:inset 0 1px 0 rgba(255,255,255,.025),0 5px 14px rgba(0,0,0,.18);text-decoration:none!important} .cfStaticCard{transition:transform .22s ease,border-color .22s ease,background .22s ease,box-shadow .22s ease,filter .22s ease} /* HOVER AWAL */ .cfStaticCard:hover{transform:translateX(3px) translateY(-1px);border-color:rgba(105,235,255,.65);background:linear-gradient(180deg,rgba(10,31,53,.94),rgba(7,18,35,.86));box-shadow:inset 3px 0 0 rgba(87,232,255,.48),0 0 15px rgba(65,220,255,.16),0 6px 15px rgba(0,0,0,.25);filter:brightness(1.035);text-decoration:none!important} .cfFeedSideR .cfStaticCard:hover{transform:translateX(-3px) translateY(-1px);box-shadow:inset -3px 0 0 rgba(87,232,255,.48),0 0 15px rgba(65,220,255,.16),0 6px 15px rgba(0,0,0,.25)} /* SOFT DIGITAL ACCENT */ .cfStaticCard:before{content:"";position:absolute;z-index:3;left:5px;right:5px;top:3px;height:1px;background:linear-gradient(90deg,rgba(91,218,244,.7) 0 22%,transparent 22% 30%,rgba(154,88,211,.42) 30% 43%,transparent 43% 75%,rgba(91,218,244,.32) 75% 88%,transparent 88%);pointer-events:none} .cfStaticCard:after{content:"";position:absolute;z-index:2;left:0;bottom:0;width:34%;height:1px;background:linear-gradient(90deg,rgba(79,204,232,.28),transparent);pointer-events:none} .cfFeedSideR .cfStaticCard:after{left:auto;right:0;background:linear-gradient(270deg,rgba(79,204,232,.28),transparent)} /* IMAGE */ .cfStaticThumb{position:relative;display:block;height:49px;margin-top:2px;overflow:hidden;border-radius:4px;border:1px solid rgba(105,190,220,.2);background:#091725;box-shadow:inset 0 0 12px rgba(23,102,137,.08);transition:border-color .24s ease,box-shadow .24s ease} .cfStaticThumb:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(61,184,216,.025),transparent 45%,rgba(28,120,152,.05));pointer-events:none} .cfStaticThumb img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .28s ease,filter .28s ease} .cfStaticCard:hover .cfStaticThumb{border-color:rgba(107,210,237,.38);box-shadow:0 0 9px rgba(72,201,230,.09)} .cfStaticCard:hover .cfStaticThumb img{transform:scale(1.055);filter:brightness(1.08) contrast(1.025)} /* TEXT */ .cfStaticCard>b{display:block;margin-top:4px;overflow:hidden;color:#e7f4f8;font-size:15px;line-height:17px;font-weight:400;white-space:nowrap;text-overflow:ellipsis;transition:color .2s ease,text-shadow .2s ease} .cfStaticCard small{display:block;margin-top:2px;overflow:hidden;color:#73bfd4;font-size:10px;line-height:11px;font-weight:500;white-space:nowrap;text-overflow:ellipsis;text-transform:uppercase;transition:color .2s ease} .cfStaticCard:hover>b{color:#f3fcff;text-shadow:0 0 5px rgba(91,215,242,.17)} .cfStaticCard:hover small{color:#91d9e9} /* SKELETON */ .cfFeedSkeleton:before{content:"";position:absolute;inset:5px;border-radius:4px;background:linear-gradient(90deg,rgba(65,174,205,.025) 20%,rgba(92,194,223,.09) 45%,rgba(65,174,205,.025) 70%);background-size:220% 100%;animation:cfSkeleton 1.4s linear infinite} @keyframes cfSkeleton{to{background-position:-220% 0}} /* MODEL */ .cfStaticModelZone{position:absolute;left:50%;top:0;bottom:0;z-index:5;width:38%;transform:translateX(-50%);pointer-events:none} .cfStaticModelWrap{position:absolute;left:50%;bottom:0;height:calc(100% - 2px);width:var(--cf-model-width,180px);transform:translateX(-50%);opacity:0;filter:blur(7px) brightness(1.7);clip-path:inset(100% 0 0 0)} .cfStaticModel{display:block;position:absolute;inset:0;z-index:1;width:100%!important;height:100%!important;max-width:none!important;object-fit:contain!important;object-position:center bottom} .cfStaticModelScan{z-index:3;opacity:0;filter:brightness(1.45) saturate(.55) sepia(.08) hue-rotate(145deg) drop-shadow(0 0 2px rgba(108,236,255,.68));clip-path:inset(0 0 97% 0)} /* MODEL LOADING */ .cfModelLoading{position:absolute;inset:0;z-index:8;display:flex;align-items:center;justify-content:center;transition:opacity .3s ease,visibility .3s ease} .cfModelLoadBox{min-width:105px;padding:8px 10px;background:rgba(4,15,30,.74);border:1px solid rgba(105,226,255,.48);border-radius:5px;box-shadow:0 0 15px rgba(65,215,255,.12);text-align:center} .cfModelLoadBox b{display:block;color:#c9f6ff;font-size:8px;line-height:1;letter-spacing:.7px;font-weight:500} .cfModelLoadIcon{display:block;width:13px;height:13px;margin:0 auto 6px;border:1px solid rgba(113,229,255,.22);border-top-color:#80edff;border-right-color:#80edff;border-radius:50%;animation:cfModelSpin .65s linear infinite} .cfModelLoadBar{position:relative;display:block;width:72px;height:2px;margin:7px auto 0;overflow:hidden;background:rgba(90,217,255,.12)} .cfModelLoadBar i{position:absolute;top:0;bottom:0;left:-45%;width:45%;background:linear-gradient(90deg,transparent,#73eaff,transparent);animation:cfLoadBar 1.1s linear infinite} @keyframes cfModelSpin{to{transform:rotate(360deg)}}@keyframes cfLoadBar{to{left:100%}} /* REVEAL */ .cfStaticModelZone.cfModelReady .cfModelLoading{opacity:0;visibility:hidden}.cfStaticModelZone.cfModelReady .cfStaticModelWrap{animation:cfModelReveal .85s cubic-bezier(.2,.75,.25,1) forwards} @keyframes cfModelReveal{0%{opacity:0;filter:blur(7px) brightness(2);clip-path:inset(100% 0 0 0);transform:translateX(-50%) translateY(8px) scale(.97)}45%{opacity:1;filter:blur(1px) brightness(1.35);clip-path:inset(30% 0 0 0)}100%{opacity:1;filter:none;clip-path:inset(0);transform:translateX(-50%) translateY(0) scale(1)}} .cfModelRevealFlash{position:absolute;z-index:4;left:0;right:0;top:100%;height:3px;opacity:0;background:linear-gradient(90deg,transparent 5%,#bffaff 28%,#fff 50%,#bffaff 72%,transparent 95%);box-shadow:0 0 5px #fff,0 0 10px rgba(78,225,255,.7);pointer-events:none} .cfStaticModelZone.cfModelReady .cfModelRevealFlash{animation:cfRevealFlash .82s cubic-bezier(.2,.7,.3,1) .05s 1} @keyframes cfRevealFlash{0%{top:100%;opacity:0}12%{opacity:.8}80%{opacity:.55}100%{top:0;opacity:0}} /* SCAN */ .cfStaticModelZone.cfModelReady .cfStaticModelScan{animation:cfModelScanner 2.8s ease-in-out 1.1s infinite alternate} @keyframes cfModelScanner{0%{clip-path:inset(0 0 97% 0);opacity:0}6%{opacity:.55}50%{opacity:.58}94%{opacity:.55}100%{clip-path:inset(97% 0 0 0);opacity:0}} .cfStaticEmpty{height:100%;display:flex;align-items:center;justify-content:center;text-align:center;color:#78bdd7;font-size:12px} @media(max-width:600px){ .cfFeedSide{width:30%}.cfFeedSideL{left:1.5%;transform:translateY(-50%) perspective(800px) rotateY(15deg)}.cfFeedSideR{right:1.5%;transform:translateY(-50%) perspective(800px) rotateY(-15deg)}.cfStaticModelZone{width:40%} } @media(max-width:420px){ .cfFeedSide{width:29%;height:290px}.cfFeedSideL{left:1%;transform:translateY(-50%) perspective(700px) rotateY(13deg)}.cfFeedSideR{right:1%;transform:translateY(-50%) perspective(700px) rotateY(-13deg)}.cfStaticModelZone{width:42%}.cfStaticCard,.cfFeedSkeleton{height:90px;padding:4px}.cfStaticThumb{height:47px}.cfStaticCard>b{font-size:13px;line-height:16px}.cfStaticCard small{font-size:9px} } @media(max-width:320px){ .cfFeedSide{width:28%}.cfFeedSideL{transform:translateY(-50%) perspective(650px) rotateY(11deg)}.cfFeedSideR{transform:translateY(-50%) perspective(650px) rotateY(-11deg)}.cfStaticModelZone{width:44%}.cfStaticThumb{height:45px}.cfStaticCard>b{font-size:12px} } </style> <script> //<![CDATA[ (function(){"use strict"; var W=document.querySelectorAll("[data-cf-static-feed]");if(!W.length)return; /* MODEL */ W.forEach(function(w){ var z=w.querySelector(".cfStaticModelZone"),im=w.querySelector(".cfStaticModelMain"),wrap=w.querySelector(".cfStaticModelWrap");if(!z||!im||!wrap)return; function ready(){if(z.classList.contains("cfModelReady"))return;var h=z.clientHeight-2,r=im.naturalWidth&&im.naturalHeight?im.naturalWidth/im.naturalHeight:.56;wrap.style.setProperty("--cf-model-width",Math.round(h*r)+"px");requestAnimationFrame(function(){z.classList.add("cfModelReady")})} if(im.complete&&im.naturalWidth>0)ready();else im.addEventListener("load",ready,{once:true}); im.addEventListener("error",function(){var l=z.querySelector(".cfModelLoadBox b");if(l)l.textContent="MODEL UNAVAILABLE"},{once:true}); }); /* CONFIG */ var ROOT=(location.origin||location.protocol+"//"+location.host).replace(/\/$/,""),MAX_FEED=30,NEED=6,FEED=ROOT+"/feeds/posts/default?alt=json-in-script&max-results="+MAX_FEED, FALLBACK="data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='144' viewBox='0 0 256 144'%3E%3Crect width='256' height='144' fill='%23091b28'/%3E%3Cpath d='M0 112l56-52 44 39 35-30 121 75H0z' fill='%23142f40'/%3E%3Ccircle cx='196' cy='38' r='14' fill='%23254c60'/%3E%3C/svg%3E"; function esc(s){return String(s||"").replace(/[&<>"']/g,function(c){return{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]})} function decodeHtml(s){var t=document.createElement("textarea");t.innerHTML=String(s||"");return t.value} function clean(u){return decodeHtml(String(u||"").replace(/\\u003d/g,"=").replace(/\\u0026/g,"&")).replace(/\\/g,"").trim()} /* GITHUB VIEW URL -> RAW */ function raw(u){ u=clean(u); var m=u.match(/^https?:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/(.+)$/i); if(m)return"https://raw.githubusercontent.com/"+m[1]+"/"+m[2]+"/"+m[3]; m=u.match(/^https?:\/\/github\.com\/([^\/]+)\/([^\/]+)\/raw\/(.+)$/i); if(m)return"https://raw.githubusercontent.com/"+m[1]+"/"+m[2]+"/"+m[3]; return u } /* ADAPTIVE IMAGE SIZE */ function pickSize(w){w=parseInt(w,10)||256;if(w<=128)return"s128";if(w<=256)return"s256";if(w<=320)return"s320";if(w<=640)return"s640";return"s800"} function isCFImage(u){return /^https?:\/\/img\.codeflare\.net\//i.test(u||"")} function originalImage(u){u=raw(u);if(!u)return FALLBACK;return isCFImage(u)?u.replace(/\/s\d+(?:-c)?\//i,"/s800/"):u} function resize(u,size){u=raw(u);if(!u)return FALLBACK;u=u.replace(/\/s\d+(?:-c)?\//i,"/"+size+"/");u=u.replace(/\/w\d+(?:-h\d+)?(?:-[^\/]+)?\//i,"/"+size+"/");u=u.replace(/=s\d+(?:-c)?(?:-[^?#&]*)?(?=$|[?#&])/i,"="+size);return u} function extract(h){ if(!h)return""; h=decodeHtml(h); var box=document.createElement("div");box.innerHTML=h; var imgs=box.querySelectorAll("img"); for(var i=0;i<imgs.length;i++){ var n=imgs[i],u=n.getAttribute("data-src")||n.getAttribute("data-original")||n.getAttribute("data-lazy-src")||n.getAttribute("data-url")||n.getAttribute("src"); if(u&&!/^data:/i.test(u)&&!/^blob:/i.test(u))return clean(u); var ss=n.getAttribute("data-srcset")||n.getAttribute("srcset"); if(ss){ var f=ss.split(",")[0].trim().split(/\s+/)[0]; if(f)return clean(f) } } var P=[ /(https?:\/\/[^\s"'<>]+\/s\d+(?:-c)?\/[^\s"'<>]+)/i, /(https?:\/\/raw\.githubusercontent\.com\/[^\s"'<>]+)/i, /(https?:\/\/github\.com\/[^\s"'<>]+)/i, /(https?:\/\/blogger\.googleusercontent\.com\/[^\s"'<>]+)/i, /(https?:\/\/[^\s"'<>]+?\.(?:jpg|jpeg|png|webp|gif)(?:\?[^\s"'<>]*)?)/i ]; for(var x=0;x<P.length;x++){ var m=h.match(P[x]); if(m&&m[1])return clean(m[1]) } return"" } function image(e){ var candidates=[]; /* jangan langsung percaya thumbnail feed jika ada source lain */ if(e.content&&e.content.$t)candidates.push(extract(e.content.$t)); if(e.summary&&e.summary.$t)candidates.push(extract(e.summary.$t)); if(e.media$thumbnail&&e.media$thumbnail.url)candidates.push(e.media$thumbnail.url); for(var i=0;i<candidates.length;i++){ if(candidates[i])return raw(candidates[i]) } return FALLBACK } function link(e){var l=e.link||[];for(var i=0;i<l.length;i++)if(l[i].rel==="alternate"&&l[i].href)return l[i].href;return""} function date(e){var d=(e.published&&e.published.$t)||(e.updated&&e.updated.$t)||"";if(!d)return"ARTICLE";try{return new Intl.DateTimeFormat("id-ID",{day:"2-digit",month:"short",year:"numeric"}).format(new Date(d))}catch(x){return"ARTICLE"}} function key(u){return String(u||"").replace(/^https?:/i,"").replace(/\/s\d+(?:-c)?\//i,"/SIZE/").replace(/[?#].*$/,"").toLowerCase()} function parse(j){ var E=j&&j.feed&&j.feed.entry?j.feed.entry:[],P=[],UU={}; for(var i=0;i<E.length;i++){ var e=E[i],u=link(e);if(!u||UU[u])continue; UU[u]=1; P.push({ title:e.title&&e.title.$t?e.title.$t:"Untitled", url:u, image:image(e), date:date(e) }); if(P.length>=NEED)break } return P } function card(p){var src=originalImage(p.image||FALLBACK);return'<a class="cfStaticCard" href="'+esc(p.url)+'">'+'<span class="cfStaticThumb"><img src="'+esc(src)+'" data-cf-src="'+esc(src)+'" alt="'+esc(p.title)+'" loading="lazy" decoding="async"></span>'+'<b>'+esc(p.title)+'</b><small>'+esc(p.date)+'</small></a>'} function optimizeThumbs(w){if(!w)return;var imgs=w.querySelectorAll(".cfStaticThumb img[data-cf-src]");for(var i=0;i<imgs.length;i++){(function(img){var original=originalImage(img.getAttribute("data-cf-src")||""),box=img.parentNode,width=box?box.clientWidth:0;if(!original||/^data:/i.test(original))return;if(img.getAttribute("src")!==original)img.setAttribute("src",original);var wanted=resize(original,pickSize(width));if(!wanted||wanted===original)return;var test=new Image;test.onload=function(){img.setAttribute("src",wanted)};test.onerror=function(){img.setAttribute("src",original)};test.src=wanted})(imgs[i])}} function render(P){ W.forEach(function(w){ var L=P.slice(0,3),R=P.slice(3,6); var lb=w.querySelector(".cfStaticLeftItems"),rb=w.querySelector(".cfStaticRightItems"); if(lb)lb.innerHTML=L.length?L.map(card).join(""):'<div class="cfStaticEmpty">NO POSTS</div>'; if(rb)rb.innerHTML=R.length?R.map(card).join(""):'<div class="cfStaticEmpty">NO POSTS</div>'; optimizeThumbs(w) }) } /* RESPONSIVE IMAGE */ var cfResizeTimer=null;window.addEventListener("resize",function(){clearTimeout(cfResizeTimer);cfResizeTimer=setTimeout(function(){W.forEach(optimizeThumbs)},160)},{passive:true}); /* JSONP */ var CB="cfStaticFeed_"+Date.now()+"_"+Math.random().toString(36).slice(2),S=document.createElement("script"); window[CB]=function(j){ try{render(parse(j))} catch(e){console.error("CodeFlare Static Feed:",e)} finally{ try{delete window[CB]}catch(x){window[CB]=void 0} if(S.parentNode)S.parentNode.removeChild(S) } }; S.src=FEED+"&callback="+encodeURIComponent(CB);S.async=true; S.onerror=function(){ console.warn("CodeFlare Static Feed: feed gagal dimuat",FEED); try{delete window[CB]}catch(x){window[CB]=void 0} if(S.parentNode)S.parentNode.removeChild(S) }; document.head.appendChild(S); })(); //]]> </script>

    Cara Mengganti Model

    Kalau ingin memakai karakter atau model lain, saya sarankan gunakan PNG atau WebP transparan yang bisa diakses publik. Ganti URL pada .cfStaticModelMain dan .cfStaticModelScan dengan file yang sama supaya scanner tetap mengikuti bentuk model dengan tepat.

    Gunakan file transparan.
    Model dengan background putih atau solid tetap akan tampil, tetapi scanner akan mengikuti seluruh kotak gambar sehingga efek siluet menjadi kurang menarik.

    Cara Mengubah Tinggi Widget

    Tinggi awal widget saya set di .cfStaticFeed dengan nilai height:320px. Nilainya bisa dinaikkan atau diturunkan kalau area pemasangan membutuhkan ukuran yang berbeda.

    Kalau ingin mengubah ukurannya, saya biasanya mulai dari tinggi utama dulu lalu mengecek jarak antar-card di desktop dan mobile. Jangan langsung mengubah semua ukuran sekaligus karena perhitungan natural ratio sudah membantu menyesuaikan lebar model berdasarkan tinggi yang baru.

    Bagian yang Aman Dikustomisasi

    Tinggi widgetNilai height pada .cfStaticFeed.
    Warna backgroundWarna dasar pada scene dan sky.
    Warna gridDua linear-gradient pada .cfStaticFloor.
    Warna glowBorder, box-shadow, horizon, dan aura.
    URL modelGanti source model utama dan scan sekaligus.
    Kecepatan scannerDurasi 2.8s pada animasi cfModelScanner.

    Bagian JavaScript yang Sebaiknya Tidak Diubah

    ROOT dan FEEDMenjaga feed otomatis mengikuti domain aktif.
    raw(), pickSize(), originalImage(), resize()Menangani adaptive image dan struktur URL Blogger/CodeFlare/GitHub.
    extract() dan image()Mencari source gambar dari content, summary, dan media thumbnail.
    naturalWidth / naturalHeightMenjaga proporsi model.
    JSONP callbackMengambil feed dan membersihkan callback setelah selesai.
    NEED=6Layout final memang dirancang untuk tiga card kiri dan tiga card kanan.

    Widget Tidak Menampilkan Artikel?

    Kalau yang terlihat hanya skeleton atau tulisan NO POSTS, saya biasanya mengecek beberapa hal berikut lebih dulu:

    Pastikan feed Blogger aktif dan blog dapat dibaca publik.
    Pastikan kode tidak terpotong saat disalin.
    Pastikan JavaScript tidak dibuang editor.
    Gunakan gadget HTML/JavaScript, bukan editor Compose artikel.
    Buka Developer Tools → Console dan cari pesan CodeFlare Static Feed.

    Thumbnail Tidak Muncul?

    Kalau thumbnail tidak muncul, saya cek dulu apakah artikel memang mempunyai gambar yang ikut terbaca oleh feed. Engine mencoba content, summary, lalu media thumbnail. Untuk gambar CodeFlare atau GitHub, sebaiknya pertahankan struktur URL yang sudah didukung dan jangan mengubah fungsi adaptive image kalau sebelumnya sudah bekerja.

    Pada feed Blogger tipe pendek, posisi gambar di artikel juga bisa berpengaruh. Kalau hanya satu post yang kehilangan thumbnail, saya lebih memilih memeriksa gambar pada artikel tersebut lebih dulu sebelum menyentuh JavaScript widget.

    Model Tidak Muncul?

    Kalau model tidak muncul, langkah pertama saya adalah membuka URL gambarnya langsung di browser. Pastikan file bisa diakses publik, sebaiknya berupa PNG atau WebP transparan, dan pastikan model utama serta layer scanner memakai gambar yang sama.

    Kalau file gagal dimuat, label akan berubah menjadi MODEL UNAVAILABLE. Dari sini saya bisa langsung tahu bahwa masalahnya ada pada file model, bukan pada feed artikel.

    Kok Model Jadi Gepeng atau Langsing?

    Kalau bentuk model terlihat terlalu gepeng atau langsing, saya tidak menyarankan mengganti bagian natural ratio. Script membaca naturalWidth / naturalHeight setelah gambar selesai dimuat. Kalau bagian ini diganti ukuran statis, bentuk model lebih mudah berubah saat tinggi widget ikut diubah.

    Jumlah Feed Sebaiknya Tetap Enam

    Saya mempertahankan NEED=6 karena komposisi widget memang dirancang untuk tiga card di kiri dan tiga di kanan. Jumlahnya tentu bisa diubah oleh pengguna yang paham strukturnya, tetapi kalau hanya menambah angka tanpa mendesain ulang tinggi card dan ruang, tampilannya akan cepat terasa sesak.

    Lokasi Gadget yang Disarankan

    Menurut saya posisi paling enak adalah area homepage yang cukup lebar: di bawah header, setelah hero, sebelum footer, atau pada section HTML khusus. Widget juga bisa dipakai pada halaman statis selama tersedia ruang horizontal yang cukup.

    Kalau suatu saat ingin memindahkannya, saya cukup membuka Tata Letak lalu menggeser gadget ke section lain. Feed URL dan JavaScript tidak perlu disentuh karena domain dibaca otomatis.

    Bagian yang Bisa Saya Kembangkan Lagi

    Kalau saya ingin membuat variasi baru, saya biasanya mulai dari CSS: warna sky, grid, aura, glow, tinggi widget, atau gambar model. Bagian-bagian ini paling aman untuk dimainkan karena tidak mengubah cara widget mengambil artikel dari Blogger.

    Kalau memakai CodeFlare Image Engine, saya membiarkan adaptive image memilih s128, s256, s320, s640, atau s800 sesuai lebar card. Hasilnya gambar tetap terlihat tajam tanpa selalu memaksa browser mengambil file paling besar.

    Buat saya, bagian paling menarik dari widget ini bukan sekadar efek retro-nya. Feed tetap bekerja sebagai navigasi artikel terbaru yang sederhana, tetapi tampil lebih berkarakter. Domain terbaca otomatis, thumbnail menyesuaikan ukuran, model menjaga rasio aslinya, dan semua efek digital hanya menjadi lapisan visual tanpa mengubah fungsi utamanya.

    Setelah widget terpasang, saya biasanya mengeceknya sekali di desktop dan sekali di mobile: enam artikel harus muncul, thumbnail terbaca, model selesai loading, dan scanner bergerak mengikuti siluet. Setelah itu tinggal menyesuaikan warna atau model dengan gaya blog masing-masing. Selama engine feed dibiarkan tetap, widget bisa terus mengambil artikel terbaru tanpa perlu diurus setiap kali saya menerbitkan posting baru.

    No comments

    💬 Share Your Thoughts & Join the Hall of Fame!

    Punya pendapat atau tips tentang artikel ini? Tuliskan komentar kamu sekarang! 🚀

    💎 Komentar yang bermanfaat, relevan, dan positif berkesempatan tampil di CodeFlare Hall of Fame dan masuk ke Top Commentators Widget.

    👉 Comment now. Share your ideas. Get noticed on codeflare.net

    Post Top Ad

    Post Bottom Ad