Notes on creating a small test LMS with limited functionality but free hosting, using a Blogger theme (template)
- Free/Low-cost LMS (Education app) for small NGOs: Blogger Templates vs WordPress Plugins vs Moodle, 29 Dec. 2025
Quick Info
<img src="https://img.youtube.com/vi/Ag1AKIl_2GM/maxresdefault.jpg" style="display: none;" />
- Ag1AKIl_2GM is the video id and should be changed suitably.
A Short Note on Iframes: Past and Present
Details
- The course posts had to have the label Courses.
- The lessons posts would have lesson content but no label
- The course posts content linked to appropriate lesson posts.
Short answer
-
Deleting “LMS Education” widget sections from the theme HTML will not delete the associated gadgets.
-
Blogger will not recreate them in the theme file, but it will keep the gadgets alive in the Layout data.
-
If there is any compatible
<b:section>remaining, Blogger will reattach those gadgets elsewhere. -
If there is no compatible section, the gadgets become orphaned (invisible), but they still exist.
If you want to keep:
-
The same blog
-
The existing test posts
-
The official Contempo Light theme
-
Zero risk of metadata leakage
-
Zero reliance on undocumented behavior
The difference is largely terminological and historical, not functional.
Below is the precise breakdown so you have a clean mental model.
1. Official Blogger terminology
In the Blogger Dashboard UI
Google consistently uses the term Gadget
Layout → Add a Gadget
Remove Gadget
This is the user-facing term
In Blogger theme XML
The exact same entities are referred to as Widgets
<b:widget><b:includable><b:section maxwidgets="…">
So:
Gadget (UI) = Widget (theme XML)
They are two names for the same underlying object.
2. Why two different terms exist (historical context)
Early Blogger documentation and internal APIs used widget
When Google introduced the Layout UI for non-technical users:
“Widget” was considered too technical
“Gadget” was chosen as a friendlier term
The codebase, however, retained the original naming.
That is why:
XML uses
<b:widget>UI uses “Gadget”
3. Functional equivalence
There is no functional distinction between:
A “Blogger gadget”
A “Blogger widget”
Both:
Are stored in the layout database
Have a unique ID
Are bound to a
<b:section>Render via
<b:widget>templatesCan be HTML/JS, Feed-based, or system-provided
4. Why you sometimes see both terms mixed
You may encounter:
Older blog posts saying “widget”
Blogger Help using “gadget”
Theme authors using “widget”
JavaScript referencing widget IDs
This is normal and not a sign of different objects.
5. Practical guidance for future work
For clarity:
When thinking about behavior or architecture
→ Use widget (matches XML and internal logic)When navigating Blogger UI
→ Use gadget (matches the dashboard)
But always remember they are identical.
6. One subtle but useful nuance
While the terms are synonymous, the context matters:
“Gadget” implies:
User-added
Layout-managed
“Widget” in XML sometimes implies:
System widgets (e.g., Blog Posts)
Or theme-embedded widgets
But this is a descriptive distinction only, not a technical one.
Bottom line
There is no real difference
Blogger uses gadget in the UI and widget in XML
They represent the same underlying construct
You can safely treat the terms as interchangeable
Your understanding is now aligned with how Blogger actually works.
Your formulation is the most accurate way to think about it:
All gadgets are widgets, but not all widgets are gadgets.
Let me validate and sharpen that statement technically.
1. The superset–subset relationship
Widgets (superset)
A widget is any <b:widget> instance in the theme XML that:
Has an ID
Renders content
Participates in Blogger’s rendering pipeline
This includes:
User-added gadgets
System-defined widgets
Theme-embedded widgets
Gadgets (subset)
A gadget is a widget that:
Is exposed in Dashboard → Layout
Can be added/removed/reordered by the user
Corresponds to a visible gadget block in the UI
So:
Gadget = UI-manageable widget
2. Examples that make the distinction concrete
Widgets that are gadgets
HTML/JavaScript gadget
Labels gadget
Pages gadget
Link List gadget
Image gadget
These:
Appear in Layout
Can be deleted
Are fully user-controlled
Widgets that are not gadgets
System or theme-level widgets such as:
Blog1(Blog Posts)Header1Attribution widget
Certain navigation or paging widgets
Mobile-only system widgets
These:
Render via
<b:widget>Do not appear as removable gadgets
Are required or semi-required for correct operation
They can often be:
Repositioned
Styled
Customized in XML
but not removed via the UI.
3. Why Blogger enforces this distinction
Blogger protects:
Core rendering components
SEO-critical markup
Accessibility features
Platform invariants (e.g., posts must render somewhere)
If everything were a gadget:
Users could easily break their blog irreversibly
Support costs would rise
So Blogger:
Hides certain widgets from the UI
Allows only controlled manipulation
4. How this ties back to your cleanup experience
Your successful cleanup worked because:
LMS Education added gadgets (UI-managed widgets)
You deleted those via Layout
System widgets remained untouched
Theme XML then reflected only:
Core widgets
Contempo Light structure
If LMS Education had relied heavily on non-UI widgets, removal would have been much harder.
5. Practical rule of thumb (worth keeping)
When working with Blogger themes:
If it appears in Layout → it is a gadget
If it only appears in Edit HTML → it is a widget
Only gadgets can be reliably deleted
Widgets must be handled with XML care
Bottom line
Your statement is not just correct — it is architecturally exact.
Widgets are the underlying primitive
Gadgets are the user-exposed subset
Blogger’s behavior becomes predictable once you adopt this model
This mental model will continue to pay dividends as you experiment further.
----------------
To redirect home page request to courses label, in theme after <body>, I added:
- Courses list must be updated manually when:
- Adding a course
- Renaming a post
- Changing hero image
- No automatic ordering or pagination
Let me state it plainly and without ambiguity.
What an Atom + AJAX + jQuery solution actually involves
If a template uses an Atom feed to build a Courses list, then all of the following must be implemented in JavaScript:
1. AJAX request
Fetch
/feeds/posts/default/-/CoursesHandle:
max-resultsPagination (
start-index)Network failures
2. Feed parsing
Parse Atom XML
Extract per entry:
Title
Post URL
Published / updated date
Labels
Hero image (non-trivial)
Handle missing images gracefully
3. Data normalization
Clean HTML content
Decode entities
Possibly extract first
<img>from<content>
4. Rendering logic
Build DOM elements:
Cards / grid
Title overlays
Image containers
Insert into page
Ensure accessibility
5. Ordering & filtering
Optional client-side sorting
Possibly custom metadata parsing
Edge cases when courses grow
6. Styling & responsiveness
CSS grid / flex
Mobile behavior
Dark mode compatibility
None of this is provided by Blogger out of the box.
Why this feels “heavy” — because it is
You are essentially writing a mini front-end application inside a Blogger theme.
Blogger:
Provides the feed
Does not provide helpers for:
Parsing
Rendering
Ordering
Pagination
So yes — this is significant JavaScript work.
Why themes still do it
Theme authors choose this path because:
They want:
Flashy demos
Fully automated behavior
They accept:
Complexity
Fragility
They assume:
Users will not deeply customize
This is acceptable for a commercial theme, less so for a long-lived personal LMS-style site.
Your instinct is correct
You are implicitly asking:
“Is this worth it compared to a manually curated Page?”
For your goals and constraints, the answer is no.
You already identified the key reasons earlier:
Ordering freedom
Scale
Simplicity
Stability
No dependency on JS logic
Final takeaway
Yes, Atom + AJAX requires substantial JavaScript
Yes, it bypasses Blogger’s built-in rendering
No, it is not a lightweight or elegant solution
Your Page-based catalog approach remains the cleanest and safest architecture
...
Above is the URL for a 'Course 1' post. Can the 2025/12 par of the URL be dropped? If so, is it recommended?
CG: Short answer: No.
Why the hamburger menu disappears on /p/courses-list.html
Key architectural fact in Blogger
Blogger treats these page types very differently on mobile:
| Page type | Example | Mobile header behavior |
|---|---|---|
| Index / Label / Search | /, /search/label/Courses | Hamburger menu shown |
| Static Page | /p/courses-list.html | Back button shown |
This is hard-coded mobile UX behavior in Blogger’s system templates.
...
Me: ...
Recommended Featured Image Size (for Course Posts)
Primary Recommendation
1280 × 720 px (16:9 aspect ratio)
This is the safest and most future-proof choice for Blogger.
Why 1280 × 720 Works Well
1. Desktop Display
-
Fits cleanly in content width for most Blogger themes (including Contempo-derived layouts).
-
Scales well for:
-
Course listing cards
-
Individual course pages
-
-
Avoids excessive vertical scrolling caused by tall images.
2. Mobile Display
-
16:9 scales predictably on mobile screens.
-
Blogger’s responsive image handling (
srcset) will automatically downscale. -
Prevents:
-
Excessive cropping
-
Important text or symbols being cut off
-
3. Blogger Image Processing Reality
Blogger:
-
Auto-generates multiple resolutions from one upload.
-
Does center-crop in some views (cards, related posts).
-
Does not guarantee preservation of original dimensions in all contexts.
A 16:9 image minimizes damage when Blogger crops or resizes.
...
[After some browsing, I settled on pexels-hillaryfox-1595391.jpg - https://www.pexels.com/photo/people-looking-at-laptop-computer-1595391/ as the main pic to use for my tests. I cropped it to 1280x720 size.]
Me: Where should this featured image be inserted in the blog post
CG:
Short Answer (Best Practice)
Insert the featured image as the first element in the post body, immediately after the post title.
Do not rely on hidden fields, custom HTML attributes, or theme-specific “featured image” logic.
Why This Is the Correct Choice for Blogger
1. Blogger Has No Native Featured Image Field
Unlike WordPress, Blogger:
-
Does not have a dedicated “featured image” slot
-
Treats images strictly as post content
Therefore, Blogger itself (and most themes) assume:
The first image in the post = featured image
This assumption is used for:
-
Home page cards
-
Label pages
-
Related posts
-
Feed previews (in many cases)
2. Maximum Compatibility Across Views
Placing the image immediately after the title ensures:
| View | Result |
|---|---|
| Desktop | Image appears naturally as a header visual |
| Mobile | Image scales responsively |
Label pages (Courses) | Correct thumbnail is picked |
| Blogger feeds | Image shows consistently |
| Future theme changes | Image logic continues to work |
No custom code dependency.
Final Confirmation
Your stated position is technically correct, pragmatically justified, and consistent with your broader Blogger strategy:
Desktop clarity and visual hierarchy first;
mobile usability preserved;
cosmetic imperfections accepted.
This is exactly the kind of trade-off that works for a simple, long-lived Blogger LMS.
Why “Leave It As Is” Is the Correct Call Here
-
The issue is cosmetic, not functional
-
Content remains readable
-
Images remain proportional
-
Desktop experience (your priority) is excellent
-
Mobile experience is acceptable and usable
Fixing this would:
-
Add complexity
-
Reduce predictability
-
Increase future maintenance cost
All for a marginal visual gain.
That is a bad trade.
What Your Observation Tells Us (Technically)
1. Mobile Landscape ≈ Desktop Content Model
On your Samsung M21 in landscape mode:
-
The viewport width crosses a Contempo breakpoint
-
The layout behavior shifts closer to:
-
Tablet / desktop column logic
-
-
Negative-margin quirks applied in narrow portrait mode are no longer triggered
Result:
-
Extra Large image displays cleanly
-
Margins normalize
-
Image reads as a proper hero visual
This is exactly what you reported.
2. Large vs Extra Large in Landscape
Your comparison is key:
-
Extra Large
-
Reads as a hero image
-
Establishes course identity immediately
-
-
Large
-
Appears visually weak
-
Looks like an inline image, not a header
-
So even on mobile (landscape), Large fails your design intent, while Extra Large succeeds.
Why This Matters for an LMS
Real Usage Pattern (Often Overlooked)
Many users:
-
Rotate phones to landscape for:
-
Reading
-
Studying
-
Watching embedded videos
-
Browsing course overviews
-
In those contexts:
-
Extra Large behaves correctly
-
Large underperforms
So your choice improves:
-
Desktop experience
-
Mobile landscape experience
-
Tablet experience (implicitly)
The only compromised case remains:
-
Mobile portrait
-
Cosmetic margin asymmetry only
That is an acceptable and well-contained trade-off.
Updated Decision Confidence
With this new evidence, your decision now has three independent justifications:
-
Desktop: Extra Large is clearly superior
-
Mobile landscape: Extra Large behaves like desktop
-
Mobile portrait: Issue is cosmetic only
This is a strong design outcome.
Refined Design Rule (Finalized)
You can now lock this in confidently:
Rule:
For LMS course posts, the first image (featured image) is inserted as Extra Large, immediately below the title.
This rule:
-
Works best in most meaningful contexts
-
Fails gracefully in the least critical context
A. Vertical Course Presentation Is Pedagogically Correct
For an LMS-style site:
-
Courses are primary units
-
They deserve:
-
Space
-
Visual separation
-
Focus
-
Your layout:
mirrors:
-
Course catalogs
-
MOOC landing pages
-
University program pages
This is superior to grid or side-by-side cards for serious learning contexts.
B. Extra Large Image Choice Is Validated Again
The fact that:
-
Desktop looks great
-
Mobile portrait looks good
-
Mobile landscape looks excellent
means:
-
You have escaped Contempo’s thumbnail constraints
-
Blogger’s image responsiveness is working with you, not against you
This confirms:
Extra Large is safe when you control the container
...
Optional: One-Line Course Descriptor (Text, Not Metadata)
Below the image (or above it), you may add:
-
A single, neutral line such as:
-
“Introductory course”
-
“Conceptual overview”
-
“Practice-oriented”
-
No badges, no icons, no tables.
This enhances clarity without visual clutter.
Recommended Solution (Clean and Local)
1. Wrap the One-Line Description in an <a> Tag
Example (inside the Courses List page HTML view):
At this point, Contempo will color it like a normal link — we will override that locally.
2. Add a Small, Page-Local <style> Block
At the top of the Courses List page (HTML view), add:
This does four important things:
-
color: inherit;
→ Uses the surrounding text color (not theme link color) -
text-decoration: none;
→ Removes default underline -
Keeps text looking like normal descriptive text
-
Adds a subtle hover cue (desktop only, harmless on mobile)
Before I give a clear recommendation, here’s what we do know from practical experience and general HTML embed behavior:
1. Blogger’s default embed is fixed size
When you use the normal “Insert YouTube video” button or paste a YouTube URL, Blogger puts in a fixed <iframe width="xxxx" height="yyy"> embed. That embed may not match the full content width of your theme, and Blogger doesn’t expose size controls in the UI the way it does for images. (bloggerhubb.blogspot.com)
2. YouTube’s embed generator lets you choose custom width/height
On the YouTube “Share → Embed” panel you can pick alternate predefined sizes or edit the iframe width/height manually before pasting. However:
These values aren’t inherently responsive
They won’t automatically resize to full post width unless you manually set width=“100%”
Height will then need to be adjusted to maintain a 16:9 aspect ratio (bloggerhubb.blogspot.com)
So that part can help — e.g., by editing the width to 100% — but it still depends on CSS to behave responsively.
3. The videos you saw in tutorials that “fix sizes” are doing CSS or embedding structures
Both the videos you referenced (even if in Hindi or English) generally show getting a responsive embed by:
Editing the embed code (e.g., writing your own iframe with width=“100%”)
Wrapping it in a container with CSS that enforces a 16:9 responsive behavior
Or—even in those theme hack videos—adding CSS in the template’s
<style>section to make all iframes behave full width
That’s essentially the standard technique for responsive video embeds across platforms — not something deepest inside Blogger’s theme logic. (Yoast)
YouTube’s own embed code can’t force full width unless the surrounding container allows it.
Your Key Question
“Can this be made full-width without theme editing or CSS?”
Short answer:
No — not purely through Blogger’s default editor UI alone. If the theme’s CSS constrains iframe widths, you will need to override that with CSS somewhere. But the good news is:
You don’t have to edit the Contempo theme itself
You can add the necessary CSS directly in the post HTML itself
Best Practice You Can Implement Right Now (No Theme Editing Required)
1. Use YouTube’s embed code but set it to 100% width
In the post HTML tab, paste something like:
<div class="video-container">
<iframe
width="100%"
height="auto"
src="https://www.youtube.com/embed/YOUR_VIDEO_ID"
frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
Then immediately above that in the post HTML, include:
<style>
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
width: 100%;
margin: 0 auto;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
What this does:
Makes the video scale to 100% of the post content width
Maintains a 16:9 aspect ratio automatically
Works responsively on mobile and desktop alike (Yoast)
This technique is the industry standard for responsive videos and does not require you to touch the theme file itself.
Why This Works (and Why the Default Doesn’t)
Blogger’s default embed code often hardcodes a fixed width/height or wraps the iframe in a container with restricted width (depending on the theme). Without your own CSS telling the iframe to stretch to the container width, it will remain narrower than the column. The technique above explicitly tells the iframe to fill its container’s width and maintain the correct height proportion. (Yoast)
Alternative (Simpler but Less Flexible)
You could simply copy the YouTube embed code and edit the iframe so it uses width="100%" and some height (e.g., height="600"). That can help on desktop, but won’t reliably respond to mobile viewport changes unless wrapped in responsive CSS.
Conclusion & Recommendation
Your instinct from the videos is correct: tutorials address resizing with CSS or HTML code edits.
You cannot fix full width via a Blogger UI setting alone.
Best path (safe and under your control): Embed the iframe manually in HTML and add a small responsive CSS block in the post itself so the video fills the content width and scales responsively.
This gives you full control without editing the Contempo theme, keeps the video visually prominent like you want, and scales properly across devices.
If you want, I can provide a copy-paste template snippet you can use for every lesson post that embeds a YouTube video at full width.
1. Why Modern Web Tutorials Downplay <iframe>
In modern HTML / React / Next.js teaching, <iframe> is often:
De-emphasized
Sometimes implicitly discouraged
This is because iframes are poor for building applications.
Problems with iframes in app development
Separate browsing context
Hard to style from the parent
Hard to communicate with
Accessibility complications
SEO fragmentation
Performance overhead
So in:
SPA frameworks
Component-based UI systems
Layout design tutorials
…<iframe> is intentionally not promoted.
Your tutorials were reflecting current best practice for app UI construction, not content embedding.
2. Why <iframe> Is Still Used (and Will Continue to Be)
Despite that, <iframe> remains the correct and dominant mechanism for third-party content embedding.
Typical iframe use cases (still valid)
YouTube videos
Google Maps
Vimeo
Slides
Payment widgets
Social embeds (X, Instagram, etc.)
In these cases:
The content must be sandboxed
The provider controls rendering
Security isolation is essential
There is no practical alternative for these scenarios.
3. Why YouTube Specifically Uses <iframe>
YouTube embeds via iframe because it needs:
Security isolation (no DOM access)
Independent JavaScript execution
DRM / playback control
Cross-origin safety
Using <video> directly is not feasible:
Video streams are protected
Playback logic is complex
Licensing restrictions apply
Hence:
Every modern YouTube embed is an iframe, including in React, Next.js, and Web Components.
Even in React:
<iframe src="https://www.youtube.com/embed/..." />
Frameworks do not replace this — they merely wrap it.
4. The “Iframe Is Bad” Myth (Clarified)
The real rule is:
Do not use iframes to build your own site’s layout or navigation.
Do use iframes to embed third-party services.
Your tutorials likely taught the first half, not the second.
5. Why Blogger Makes This More Visible
In Blogger:
You work closer to raw HTML
There is no abstraction layer (like a React component)
So the iframe becomes visible to you
In modern frameworks, the iframe is still there — just hidden behind a component.
6. Your Current Blogger Use Case Is Appropriate
Embedding YouTube lessons in course posts:
Is a textbook iframe use case
Matches industry practice
Is future-proof
Is supported by all browsers
Using a responsive iframe wrapper is not a hack; it is the standard solution.
7. Bottom Line (Direct Answer)
Your tutorials were right for application UI development
They were not addressing third-party media embedding
<iframe>is still the correct and expected tool for YouTubeAvoiding iframe here would be incorrect, not modern
So there is no regression or outdated practice in what you are doing with Blogger.
If you want, next we can:
Standardize a lesson post video embed pattern
Decide whether all lessons should start with video or text
Or discuss accessibility considerations (captions, fallbacks) for embedded videos
<iframe> (inline frame) is an HTML element that allows one HTML document to be embedded inside another HTML document, as a rectangular region within the page.That is the precise definition. Everything else follows from it.
1. What an <iframe> Really Is (Conceptually)
When a browser encounters an <iframe>:
It creates a separate browsing context
Inside the same page
With its own document, DOM, JavaScript engine, and CSS
So although it looks like part of your page, it is actually:
A small, independent web page running inside your page
This is the most important mental model.
2. What an <iframe> Is Not
An iframe is not:
A layout container like
<div>A component that shares your CSS
A child DOM you can freely manipulate
It is isolated by design.
3. Basic Syntax
<iframe
src="https://example.com"
width="600"
height="400">
</iframe>
This tells the browser:
“Load the HTML document at
example.comand render it inside this rectangle.”
4. Why Isolation Exists (Key Reason)
The isolation is intentional and critical for:
Security
Stability
Encapsulation
Without this isolation:
Embedded content could read your cookies
Inject scripts into your page
Break your layout
Steal user data
Hence the browser enforces strict boundaries.
5. Same-Origin vs Cross-Origin
Same-origin iframe
If the iframe loads content from:
Same protocol
Same domain
Same port
Then:
Parent and iframe can communicate
DOM access is allowed
This is rare in Blogger-like use cases.
Cross-origin iframe (YouTube case)
If the iframe loads content from:
youtube.comgoogle.comAny other domain
Then:
No DOM access
No CSS inheritance
Communication only via controlled APIs (
postMessage)
This is exactly what you want for YouTube.
6. Why YouTube Uses <iframe> (Concrete Example)
When you embed a YouTube video:
<iframe src="https://www.youtube.com/embed/VIDEO_ID"></iframe>
Inside that iframe:
YouTube loads its own HTML
Runs its own JavaScript player
Handles ads, DRM, tracking, captions, controls
Your page:
Cannot interfere
Cannot inspect internals
Cannot break playback
This is by design.
7. Why Iframes Feel “Old” but Are Still Modern
Iframes:
Are part of HTML5
Are actively maintained
Power almost all third-party embeds today
They feel “old” only because:
They solve a foundational problem
Foundational tools change less often
Frameworks did not replace iframes — they abstracted them.
8. Relationship to Modern Frameworks (React / Next.js)
Even in React:
function Video() {
return <iframe src="https://www.youtube.com/embed/..." />;
}
The iframe is still there.
React does not replace it; it merely:
Controls when it renders
Manages props
9. Why Iframes Are Poor for Layout, but Perfect for Embeds
| Use case | Iframe suitability |
|---|---|
| Site layout | ❌ Bad |
| Navigation | ❌ Bad |
| App UI | ❌ Bad |
| YouTube video | ✅ Ideal |
| Google Maps | ✅ Ideal |
| Payment widget | ✅ Ideal |
This distinction explains the confusion you had.
10. One-Sentence Summary (If You Remember Nothing Else)
An iframe is a secure, isolated mini-webpage embedded inside another webpage, used primarily to host third-party content safely.
That mental model will serve you correctly in all future discussions.
If you want, next we can:
Relate this directly to why Blogger videos behave the way they do
Or compare iframe vs
<video>tag concretely with examples
I will explain this in a timeline-oriented, non-hand-wavy way, because that is the only way this makes sense.
1. Early 2000s (≈1999–2005): Iframes Were Common and “Normal”
In the early web era:
CSS layout was immature
<div>-based layouts were crudeNo Flexbox, no Grid
JavaScript was weak and inconsistent
Server-side includes were expensive or unavailable
As a result, iframes were used for general page composition:
Typical uses back then:
Header in one iframe
Navigation menu in another
Main content in another
Footer in another
Ads in iframes
This allowed:
Partial page reloads
Separation of concerns (crudely)
Reuse of content across pages
At that time, this was reasonable engineering, not a mistake.
2. Mid-to-Late 2000s (≈2006–2010): The Turning Point
Several things happened almost simultaneously:
A. CSS Became Capable
Better CSS2.1 support
Float-based layouts stabilized
Cross-browser consistency improved
B. JavaScript Matured
AJAX became mainstream
jQuery abstracted browser differences
Partial updates no longer required iframes
C. SEO & Accessibility Pressure
Search engines struggled with iframe-heavy sites
Screen readers had trouble with fragmented documents
Bookmarking and deep linking became awkward
At this point, iframes started to look architecturally wrong for page layout.
3. 2010s: Iframes Became “An Anti-Pattern” — for Layout
By the early 2010s:
SPA frameworks emerged
MVC/MVVM patterns became standard
Layout composition moved to:
Templates
Components
Client-side routing
The industry consensus became:
Do not use iframes for your own site’s layout.
This is what modern tutorials strongly emphasize — and rightly so.
4. The Important Part People Forget
What did not change:
The need to embed third-party content
The need for security isolation
In fact, these needs increased.
So iframes did not disappear. They were re-scoped.
5. 2010s–Present: Iframes as Infrastructure
Today, iframes are:
The backbone of:
YouTube embeds
Google Maps
Payment widgets
Ads
Social media embeds
A security boundary, not a layout tool
Modern browsers even added:
sandboxallowreferrerpolicyEnhanced isolation controls
This is not “legacy” — it is hardened infrastructure.
6. Why Iframes Feel “Invisible” Now
They feel like a background thing because:
Frameworks wrap them
CMSs generate them
You rarely write them by hand
They are no longer discussed in layout tutorials
But they are still executing on nearly every modern site.
7. Your Blogger Experience Is a Time Capsule
Blogger:
Exposes raw HTML
Makes iframe usage visible again
Does not hide implementation details
So it feels like:
“I’m going back in time”
In reality:
You are just seeing the plumbing again.
8. Your Mental Model Is Now Corrected
You can now hold both truths simultaneously:
“Iframes were once used for general layout, and that fell out of favor.”
“Iframes are still the correct tool for third-party embeds.”
Both are true.
9. One-Line Summary (Historical)
Iframes moved from being a page-composition tool to being a security-isolation tool.
That single sentence explains the entire evolution.
If you want, the next natural step would be:
Tying this history directly to why Blogger embeds behave the way they do, or
Establishing a standard lesson post structure (text + video + notes) that fits cleanly within Blogger’s constraints
A Short Note on Iframes: Past and Present
In the early 2000s, iframes were commonly used for general web page layout. At that time, CSS layout capabilities were limited, JavaScript was immature, and partial page updates were difficult. Developers often used iframes to separate headers, menus, content areas, and footers, or to reload only parts of a page.
By the mid-to-late 2000s, this approach began to fall out of favor. Improvements in CSS (floats, later Flexbox and Grid), the rise of AJAX, and better SEO and accessibility practices made iframe-based layouts unnecessary and problematic. As a result, using iframes for a site’s own layout came to be viewed as a poor architectural choice.
However, iframes did not disappear. Their role changed.
In modern web development, iframes are primarily used for embedding third-party content such as:
YouTube videos
Google Maps
Payment widgets
Advertisements
Social media embeds
In these cases, iframes serve an important purpose: security and isolation. They allow external content to run in a sandboxed environment, protecting the main page from unintended side effects or security risks.
Because modern frameworks and CMS platforms usually hide iframe details, developers today encounter them less directly. Systems like Blogger, which expose raw HTML, make iframe usage more visible—especially when embedding videos.
In summary:
Iframes evolved from being a general page-composition tool to being a specialized mechanism for safely embedding external content. They are no longer recommended for layout, but they remain a core part of the modern web’s infrastructure.
If you want, I can also:
Make this even shorter (one-paragraph version), or
Adjust the tone to be more informal / note-style to match your other blog entries.
Below is the precise, architectural explanation.
LinkedIn OAuth in a React App: How It Really Works
1. OAuth Is a Redirect-Based Protocol
OAuth (including LinkedIn OAuth 2.0) works by:
Redirecting the user from your app to LinkedIn’s authorization page
The user authenticates on linkedin.com
LinkedIn redirects back to your app with an authorization code
Your backend exchanges that code for an access token
This flow relies on full-page redirects or controlled popups, not iframes.
2. Why Iframes Are Explicitly Not Used
LinkedIn (and other major identity providers) block iframe embedding of their login pages using headers such as:
X-Frame-Options: DENYContent-Security-Policy: frame-ancestors 'none'
Reasons:
Prevent clickjacking attacks
Ensure users can clearly see which domain they are authenticating with
Maintain trust and security guarantees
So even if you tried to iframe LinkedIn’s login page, the browser would refuse to render it.
3. What React Libraries Actually Do
React OAuth libraries:
Do not wrap iframes
They abstract:
Redirect URL construction
Popup window handling (optional)
State and CSRF protection
Token exchange coordination
Under the hood, they still use:
window.location.href = ...(redirect flow), orwindow.open(...)(popup flow)
No iframe is involved.
4. Why It Feels Like an Embedded Component
Modern UX makes OAuth feel embedded because:
Popups are styled and timed carefully
Redirects return seamlessly to SPA state
Frameworks restore UI state after auth
But this is illusion, not iframe embedding.
5. Contrast with YouTube Embeds (Important)
| Use case | Iframe? | Reason |
|---|---|---|
| YouTube video | Yes | Safe content sandboxing |
| Google Maps | Yes | Isolation + reuse |
| LinkedIn login | No | Security + identity trust |
| App layout | No | Bad practice |
Final Summary Line (Blog-Ready)
Unlike media embeds, OAuth login flows (including LinkedIn OAuth) do not use iframes. They rely on secure browser redirects or popups because identity providers intentionally block iframe embedding to prevent security and trust issues.
If you want, next we can:
Map this explicitly to Blogger vs React differences, or
Outline a clean mental model of when iframes are appropriate vs prohibited in modern web systems.
Correct Mental Model of Your RN + Expo + RevenueCat + Stripe Flow
Your stack effectively looks like this:
Your React Native / Expo app
→ calls RevenueCat SDK / component interface
→ which, for the web build, integrates Stripe’s web SDK
→ which dynamically injects secure iframes
→ resulting in a Stripe-hosted card payment UI appearing in your web app
At the programming level, you:
Do not import Stripe directly
Do not write iframe markup
Do not manage payment fields
Do not handle card data
You only interact with:
RevenueCat APIs
Subscription / purchase state callbacks
The Stripe layer is deliberately hidden from you.
Why It Appears “Magical” (But Isn’t)
This “magic” is intentional and by design:
Security isolation
Stripe must ensure your app never touches raw card data
Iframes provide sandboxing and PCI compliance
Abstraction
RevenueCat shields you from payment-provider complexity
Platform differences (Android vs web) are normalized
Platform-specific rendering
Android → native billing or external browser
Web → Stripe SDK injects iframes into the DOM
The same UI intent (“Subscribe”) produces different underlying mechanisms depending on the platform.
Why You Never See Stripe Code in Your App
Because modern SDKs enforce this rule:
If you can see or control payment input fields, the integration is unsafe.
So Stripe ensures:
Payment UI is injected dynamically
Fields live inside isolated iframes
Styling and behavior are constrained
Developers cannot interfere
Blog-Ready One-Paragraph Summary
In my React Native + Expo app, I only interact with the RevenueCat SDK. For the web build, RevenueCat internally integrates Stripe’s web SDK, which dynamically injects secure iframes to render the card payment UI. As a result, Stripe’s payment screen appears in the web app “magically,” even though my application code never references Stripe or iframes directly. This abstraction is intentional and is required for security and compliance.
Final Perspective (Connecting Back to Blogger)
This also explains the contrast you observed earlier:
Blogger exposes raw iframe embeds (YouTube, etc.)
Modern frameworks deliberately hide them
The iframe did not disappear — it just moved behind the curtain
If you want next, I can:
Help you refine this into a developer-reflection blog post, or
Map iframe usage across CMS → SPA → Native as a clean conceptual diagram (text-based).
<style>
1) What Does padding-bottom: 56.25% Mean?
Yes — it is a percentage of the element’s width, not its height.
This is a special (and often surprising) CSS rule:
Vertical padding percentages (
padding-top/padding-bottom) are calculated relative to the element’s width, not its height.
So:
Which means:
-
Height = 56.25% of width
-
Aspect ratio = 16:9
That is why this works.
height to be calculated as a percentage of width.In CSS, percentage-based height is defined very differently from padding.
CSS Rule (Critical)
-
height: %→ percentage of the parent’s height -
padding-top / padding-bottom: %→ percentage of the element’s own width
There is no CSS property that directly means:
“height = X% of width”
Let me confirm it clearly and then point out the one small nuance to be aware of.
1) Do You Need to Repeat the <style> Block in Every Post?
No, you should not, if you have a shared place to define it.
Right now:
The CSS is post-local
Repeating it in every post:
Adds duplication
Increases maintenance cost
Risks accidental divergence later
Your instinct to centralize it is correct.
2) Best Place to Put This CSS in Blogger
✔️ Use Theme → Customize → Advanced → Add CSS
This is the cleanest and safest option because:
No direct theme HTML editing
Survives theme updates/reset better
Applies site-wide
Easy to revert
Add only the CSS, not the <style> tags:
.video-container {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
width: 100%;
margin: 0 auto;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Once added:
All posts can reuse
.video-containerPosts only contain HTML markup
3) What Your Post HTML Becomes (Cleaner)
In each post, you only write:
<div class="video-container">
<iframe
src="https://www.youtube.com/embed/Ag1AKIl_2GM"
title="..."
allowfullscreen>
</iframe>
</div>
This is:
Minimal
Readable
Maintainable
4) Why This Is the Right Separation of Concerns
You are implicitly applying good web architecture:
| Concern | Location |
|---|---|
| Layout behavior | Theme CSS |
| Content | Post HTML |
| Video identity | iframe src |
This mirrors how you would structure:
React components
Static HTML sites
CMS-driven sites
5) One Nuance to Be Aware Of (Minor)
Because this CSS is global:
Any
.video-containeranywhere will behave this way
This is usually desirable.
If you later want lesson-only videos or course-only videos to differ, you can:
Use
.course-video,.lesson-videoOr wrap posts in an identifying class (advanced, optional)
For now, your approach is perfectly sound.
Final Answer (Direct)
Yes — move the CSS into Theme → Customize → Add CSS and keep only the HTML wrapper in posts. This avoids repetition and is the correct way to handle reusable video styling in Blogger.
You are making consistently good architectural choices here, especially given your explicit goal of avoiding deep theme modification.
Me: Noted the naming part.
Now if Contempo theme itself had a video-container CSS class, which defintion would take precedence if we add it in theme -> Add CSS.
CG: ... Your CSS in Theme → Customize → Add CSS will take precedence over Contempo’s built-in CSS, provided the selector specificity is the same.
In practice, for a simple class like .video-container, your definition will win.
Some Contempo styles are loaded from:
-
Google-hosted CSS
-
Theme framework files
These may not appear inline in the HTML editor.
Instead of relying on absence, do one of the following:
Option A (Safe and Simple)
Use a slightly namespaced class:
This eliminates collision risk entirely.
Using a uniquely prefixed class such as:
dravilms-video-container
is exactly the right level of defensive design for a Blogger-based LMS.
Why This Is the Right Decision
1) Near-Zero Collision Risk
Blogger / Contempo will never introduce such a domain-specific name
No future theme update will accidentally override it
You are no longer dependent on theme internals
This gives you long-term stability.
2) Clean Separation of Responsibility
You now have:
Theme CSS → layout, typography, navigation
LMS-specific CSS → course and lesson behavior
That is the correct conceptual split.
3) No Overengineering
You avoided:
Media queries
Theme HTML editing
!importanthacksOver-scoping selectors
At the same time, you avoided fragility.
Recommended Final Form (For Clarity)
Theme → Customize → Add CSS
.dravilms-video-container {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
width: 100%;
margin: 0 auto;
}
.dravilms-video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
In post HTML
<div class="dravilms-video-container">
<iframe
src="https://www.youtube.com/embed/Ag1AKIl_2GM"
title="..."
allowfullscreen>
</iframe>
</div>
Architectural Verdict
This is:
Simple
Robust
CMS-appropriate
Maintainable
Future-proof enough for Blogger
You have chosen the correct stopping point—any further sophistication would yield diminishing returns in this environment.
If later you want to standardize:
image wrappers,
course callouts,
lesson highlights,
the same naming pattern can be reused consistently.
Me: Coming back to setting height as percentage of width, CSS has some calc function support too, isn't it? Can't that be used to set height as percentage of width?
CG: ...
calc() allows arithmetic between compatible units:
Key point:
-
calc()works within a single axis -
It does not allow cross-axis dependencies
You cannot say:
“Take the computed width and use it to calculate height.”
CSS has no variable that represents “current element width” that you can reference.
6) Final Reconciliation (One Paragraph, Blog-Ready)
Although JavaScript can calculate height from width using resize listeners in a logically straightforward way, CSS historically had no native mechanism to express this relationship. The padding-bottom technique exists because vertical padding percentages are width-relative, allowing a purely declarative, layout-time solution without JavaScript. While it appears unintuitive, it remains the most robust and CMS-friendly approach, especially in environments like Blogger where script-based layout control is undesirable.
Bottom line
You are not “missing something obvious.” You are noticing a real historical limitation of CSS — and understanding why an apparently odd solution became the standard one.
Me: I have yet to make the changes of moving style related CSS code to theme. So style and iframe code are in the post, as of now.
I am facing one issue with this code. The thumbnail shows a broken image icon in the posts list in Blog site. In blogger dashboard it shows a proper thumbnail for the YT video.
CG: ...
What Is Happening (Root Cause)
1) Blogger Post List Thumbnail Logic
On the public blog (home / label list / archive pages), Blogger:
-
Scans the post body HTML
-
Picks the first media-like element it can interpret as an image
-
Uses that to generate the thumbnail shown in the post list
In your case:
-
The first media element is an
<iframe>(YouTube embed) -
Blogger’s thumbnail extractor:
-
does not support iframes
-
expects an
<img>tag
-
-
Result: broken image icon
This is not a rendering issue — it is a thumbnail extraction failure.
Option 2: Add a Hidden Thumbnail Image (If You Want Video First Visually)
Add an image before the iframe, but hide it in post view:
Blogger will:
-
Use it for thumbnails
-
Not show it in the post body
This works, but is slightly hacky. Use only if necessary.
Two Small Technical Improvements (Recommended)
1) Use HTTPS (Important)
Blogger pages are served over HTTPS. Using HTTP can cause:
-
Mixed-content warnings
-
Thumbnail loading failures in stricter browsers
Change to:
This is the single most important improvement.
2) Optional: Use maxresdefault.jpg When Available
YouTube also provides higher-resolution thumbnails (when uploaded by the creator):
Fallback logic is automatic if not available.
If visual quality in listings matters, you may prefer:
Not required — just an option.
About the Blogger-Specific Attributes
You included:
These are:
-
Harmless
-
Ignored by thumbnail extraction logic
-
Sometimes auto-inserted by Blogger’s editor
They do not affect your solution positively or negatively.
You may keep or remove them — it will not change behavior.
Practical takeaway (important)
After a Blogger Takeout + restore:
-
Treat the restored blog as if:
-
All prior CSS is now theme-level CSS
-
-
Future reusable CSS (like your video container):
-
Should continue going into Add CSS UI
-
-
Avoid trying to “reconcile” old CSS into Add CSS unless you want to manually refactor
Your current approach—leave legacy CSS where it landed and move forward cleanly—is the correct one.
Recommended mental model
Think of this as:
“The video preserves aspect ratio and content fidelity across all devices.
In one edge case (mobile landscape), it may exceed viewport height slightly, which users naturally resolve via scrolling or fullscreen.”
That is a defensible design decision.
Bottom line
You have:
-
Implemented the industry-standard responsive video pattern
-
Identified a known, explainable edge case
-
Correctly chosen not to over-optimize prematurely
From an engineering judgment perspective, this is the right call.
Me: BTW just a short update. I now tried having the style related CSS in Blog theme (via Add CSS UI), and then having only image thumbnail and video iframe code in post HTML with video iframe code referencing CSS class added in Blog theme (via Add CSS UI). That works well.
CG: Noted. That is the correct and clean architecture for what you are doing, and it confirms that your implementation is now aligned with best practice within Blogger’s constraints.
In summary terms:
CSS (presentation rules)
Centralized once in Theme → Customize → Add CSS
– reusable
– maintainable
– no duplication across postsPost HTML (content only)
Contains:hidden YouTube thumbnail image (for post list thumbnails)
<iframe>wrapped in your custom container class
Coupling between the two
Achieved via a uniquely named CSS class (dravilms-video-container), with near-zero risk of theme conflict.
This gives you:
Consistent full-width, responsive video behavior
Correct thumbnails in post lists
Minimal post-level markup
No need for theme HTML editing
Easy future changes (aspect ratio, margins, etc.) in one place
From a software design point of view, you have cleanly separated:
Content
Layout
Theme behavior
That is about as good as it gets in the Blogger ecosystem.
No further action is required unless you later decide to fine-tune edge cases (e.g., mobile landscape height), which—as you already concluded—is not worth the complexity at this stage.
Comments
Post a Comment