Hey everyone,
If you regularly work with long cloze deletion cards, you know the pain: standard JavaScript auto-scrolling (scrollIntoView()) or native #answer anchors are a complete mess.
Because WebViews attempt to recalculate layouts after rendering, traditional scrolling causes horrible visual jitter, awkward bouncing, and layout blinking every single time you flip a card. Fine-tuning timing delays or scroll offsets never fully fixes it.
The GPU Solution: Bypassing the Native Scrollbar Completely
Instead of fighting the browser’s native scrollbar, this engine abandons standard window scrolling entirely.
When a long card loads, it calculates the exact vertical offset of the active cloze and applies a GPU-accelerated transform: translateY() shift to the card container. Visually, the top of the card is cleanly shifted up past the viewport boundary in milliseconds—zero window scrolling, zero layout recalculations, and absolute zero jitter on both pc and android.
The catch is, basically, the upper side of the card is just cut away. You cannot scroll up to see anything that is beyond the scope of your screen.
Credit & Inspiration
Special thanks to the Ankimin card template project. I really loved its style, and have been using it for an incredibly long time, and based my theme on top of ankimin’s.
1. Standalone Auto-Centering Snippet (For Existing Decks)
If you already have a card design you love and just want to add jitter-free cloze centering to your current note type, paste this script at the bottom of both your Front and Back templates:
HTML
<script>
(() => {
// to find the cloze
const activeCloze = document.querySelector(".cloze");
const card = document.querySelector(".card") || document.body;
if (card && activeCloze) {
// try not to break css
card.style.position = "relative";
card.style.willChange = "transform";
card.style.transition = "none";
const clozeOffset = activeCloze.offsetTop;
const viewportCenter = window.innerHeight / 2;
if (clozeOffset > viewportCenter) {
const shiftAmount = clozeOffset - viewportCenter + (activeCloze.offsetHeight / 2);
card.style.transform = `translateY(-${shiftAmount}px)`;
}
}
})();
</script>
I tested it on just standard ankimin, and probably, if your card isn’t bloated with the excessive CSS formatting, it would, probably, work.
2. Full “YazType” Cloze Template
I also built my own full card type around this auto-scroll feature. Some of the setup is shared between the Front/Back templates and the CSS to make everything look extra clean and guarantee it works smoothly every time. Plus, I added a few extra features.
Features:
- GPU Auto-Centering: of course
- Instant Definition Search (
Q): Highlight any word or phrase on your card and pressQto immediately open a target Google search ("[word] plain english definition") in a background tab. If you don’t like it, you could change the search inquiry to any other - Smart Image Zoom: Tap/click and hold any inline image to scale it up for close inspection. You can adjust the scale of the zoom in the card code.
- Adaptive Dark Mode: Clean palette inspired by Ankimin that automatically turns itself on when dark theme is active.
- Decluttered UI: I do love Ankimin and how it looks, but those tags and deck at the front of the card were absolutely unnecessary. Removed them.
Card
Front Template
HTML
<div class="yaztype-card card" id="yaztype-card">
<div class="yaztype-field question">{{edit:cloze:front clozes}}</div>
</div>
<script>
(() => {
// Center active cloze using transform Y-axis offset to bypass WebView render jitter
const card = document.getElementById("yaztype-card");
const activeCloze = document.querySelector(".cloze");
if (card && activeCloze) {
const clozeOffset = activeCloze.offsetTop;
const viewportCenter = window.innerHeight / 2;
if (clozeOffset > viewportCenter) {
const shiftAmount = clozeOffset - viewportCenter + (activeCloze.offsetHeight / 2);
card.style.transform = `translateY(-${shiftAmount}px)`;
}
}
// Quick search shortcut ('Q')
if (window.ankiSearchHandler) {
document.removeEventListener("keydown", window.ankiSearchHandler);
}
window.ankiSearchHandler = (e) => {
if (e.repeat || e.key.toLowerCase() !== "q") return;
if (["INPUT", "TEXTAREA"].includes(document.activeElement.tagName)) return;
const selectedText = window.getSelection().toString().trim();
if (selectedText) {
e.preventDefault();
const searchQuery = `${selectedText} plain english definition`;
window.open(`https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`, "anki_google_search");
}
};
document.addEventListener("keydown", window.ankiSearchHandler);
})();
</script>
Back Template
HTML
<div class="yaztype-card card" id="yaztype-card">
<div class="yaztype-field">{{edit:cloze:front clozes}}</div>
</div>
<script>
(() => {
// Center active cloze using transform Y-axis offset to bypass WebView render jitter
const card = document.getElementById("yaztype-card");
const activeCloze = document.querySelector(".cloze");
if (card && activeCloze) {
const clozeOffset = activeCloze.offsetTop;
const viewportCenter = window.innerHeight / 2;
if (clozeOffset > viewportCenter) {
const shiftAmount = clozeOffset - viewportCenter + (activeCloze.offsetHeight / 2);
card.style.transform = `translateY(-${shiftAmount}px)`;
}
}
// Quick search shortcut ('Q')
if (window.ankiSearchHandler) {
document.removeEventListener("keydown", window.ankiSearchHandler);
}
window.ankiSearchHandler = (e) => {
if (e.repeat || e.key.toLowerCase() !== "q") return;
if (["INPUT", "TEXTAREA"].includes(document.activeElement.tagName)) return;
const selectedText = window.getSelection().toString().trim();
if (selectedText) {
e.preventDefault();
const searchQuery = `${selectedText} plain english definition`;
window.open(`https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`, "anki_google_search");
}
};
document.addEventListener("keydown", window.ankiSearchHandler);
})();
</script>
Styling (CSS)
CSS
/* ==========================================================================
YazType Anki Cloze Theme
Minimalist, jitter-free cloze template with dark mode support
========================================================================== */
/* --------------------------------------------------------------------------
1. CUSTOMIZATION VARIABLES
Adjust colors, typography, layout width, and shadows here.
-------------------------------------------------------------------------- */
:root {
/* Layout & Typography */
--card-max-width: 60em; /* Maximum card width on desktop */
--card-text-align: left; /* Text alignment (left, center, justify) */
--font-size-regular: 16px; /* Main body text size */
--font-size-small: 12px; /* Secondary/small text size */
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
/* Light Mode Palette */
--text-fg: #555555; /* Default text color */
--card-bg: #ffffff; /* Main card container background */
--cloze-fg: #0db5be; /* Cloze deletion highlight color */
--box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; /* Card elevation shadow */
}
/* --------------------------------------------------------------------------
2. DARK MODE OVERRIDES
Automatic dark mode support for Anki Desktop and AnkiDroid.
-------------------------------------------------------------------------- */
.nightMode,
.night_mode,
@media (prefers-color-scheme: dark) {
:root {
--text-fg: #ffffff;
--card-bg: #23272e;
--cloze-fg: #0db5be;
--box-shadow: rgba(0, 0, 0, 0.35) 0px 8px 24px;
}
}
/* --------------------------------------------------------------------------
3. BASE CANVAS & ENVIRONMENT STYLING
-------------------------------------------------------------------------- */
html, body {
padding: 0;
background-color: #f1f1f1; /* Light mode outer canvas background */
}
.nightMode body, .night_mode body {
background-color: #181b22 !important; /* Dark mode outer canvas background */
}
.card {
letter-spacing: 0.1px;
cursor: default;
padding: 0.5em 0;
}
html:not(.mobile) .card {
padding: 10px 10px 35px 10px !important;
}
/* --------------------------------------------------------------------------
4. CARD CONTAINER (CRITICAL FOR AUTO-SCROLL ENGINE)
Note: Do not remove 'position: relative', 'transition: none',
or 'will-change: transform'. They prevent WebView rendering jitter.
-------------------------------------------------------------------------- */
.yaztype-card {
background-color: var(--card-bg);
color: var(--text-fg);
font-family: var(--font-family);
font-size: var(--font-size-regular);
line-height: 1.75;
margin: 0 auto;
max-width: var(--card-max-width);
text-align: var(--card-text-align);
word-wrap: break-word;
box-shadow: var(--box-shadow);
border-radius: 10px;
padding: 1.5em;
/* Required properties for GPU transform centering */
position: relative;
transition: none !important;
backface-visibility: hidden;
will-change: transform;
}
.yaztype-field {
font-weight: 400;
}
/* --------------------------------------------------------------------------
5. CLOZE STYLING & CUSTOMIZATION
-------------------------------------------------------------------------- */
.cloze {
color: var(--cloze-fg);
font-weight: 600;
}
/* Question state (Front side brackets [...] styling) */
.question .cloze {
/* Set to '1px dashed var(--cloze-fg)' if you prefer a bottom border on hidden clozes */
border-bottom: none;
opacity: 0.9;
}
/* --------------------------------------------------------------------------
6. MEDIA & ATTACHMENTS
Includes quick-zoom image behavior on press/hold.
-------------------------------------------------------------------------- */
img {
cursor: zoom-in;
transition: transform 0.2s ease-in-out;
max-width: 100%;
}
img:active {
transform: scale(2);
z-index: 9999;
position: relative;
}