Responsive ad slots: mobile/tablet/desktop sizing. Use when: configuring ad unit dimensions per breakpoint, hiding ads on mobile, responsive ad containers.
width=0, height=0 in AdUnit)AdUnit.width = 0 and AdUnit.height = 0 means responsive/fluidAdUnit.size_label = "responsive" or "fluid" for auto-sizinglg breakpoint{# templates/ads/fragments/placement.html #}
{% if show_ad and placement %}
<div class="ad-slot w-full overflow-hidden"
data-slot="{{ placement.slot_id }}"
{% if placement.ad_unit and placement.ad_unit.width %}
style="max-width: {{ placement.ad_unit.width }}px;"
{% endif %}>
{# Hide on mobile for sidebar placements #}
{% if "sidebar" in placement.slot_id %}
<div class="hidden lg:block">
{{ placement.render_code|safe }}
</div>
{% else %}
{{ placement.render_code|safe }}
{% endif %}
</div>
{% endif %}
# apps/ads/services/rotation.py
def select_ad_size(*, placement: AdPlacement, viewport_width: int) -> tuple[int, int]:
"""Select appropriate ad size based on viewport."""
if viewport_width < 768: # Mobile
return (320, 100) # Mobile banner
elif viewport_width < 1024: # Tablet
return (468, 60) # Standard banner
else: # Desktop
return (728, 90) # Leaderboard
{# Full-width on mobile, constrained on desktop #}
<div class="ad-slot w-full md:max-w-[728px] mx-auto">
{% render_ad_slot "blog-post-above-content" %}
</div>
{# Hidden on small screens, visible on large #}
<div class="hidden lg:block">
{% render_ad_slot "sidebar-sticky" %}
</div>
& .\.venv\Scripts\python.exe -m ruff check . --fix
& .\.venv\Scripts\python.exe -m ruff format .
& .\.venv\Scripts\python.exe manage.py check --settings=app.settings_dev