- Complete reponsitive for 575-767 and 574-

- Fix the bug of choosing 1st article on homepage news
This commit is contained in:
Warren Chen 2026-01-20 14:20:50 +09:00
parent f93d56eb1b
commit b2ab5a352d
9 changed files with 578 additions and 228 deletions

View File

@ -37,7 +37,7 @@ class CategoryMixin:
"title": category.title,
"items": ArticlePage.objects.child_of(category)
.live()
.order_by("-date")[:HORIZON_SIZE],
.order_by("-date", "-id")[:HORIZON_SIZE],
"url": category.url,
"layout": "horizon",
}
@ -47,7 +47,7 @@ class CategoryMixin:
paginator = Paginator(
ArticlePage.objects.child_of(self)
.live()
.order_by("-date"),
.order_by("-date", "-id"),
PAGE_SIZE,
)
page_number = request.GET.get("page") if request else None
@ -86,7 +86,7 @@ class CategoryMixin:
# No request means no pagination (e.g., homepage)
return {
"title": latest_page.title,
"items": ArticlePage.objects.filter(not_news=False).live().order_by("-date")[
"items": ArticlePage.objects.filter(not_news=False).live().order_by("-date", "-id")[
:NEWS_SIZE
],
"url": latest_page.url,
@ -94,7 +94,7 @@ class CategoryMixin:
else:
# Paginated view
paginator = Paginator(
ArticlePage.objects.live().order_by("-date"), PAGE_SIZE
ArticlePage.objects.live().order_by("-date", "-id"), PAGE_SIZE
)
page_number = request.GET.get("page")
@ -113,7 +113,7 @@ class CategoryMixin:
def get_trending_articles(self, request=None, exclude_ids=None):
trending_page = TrendingPage.objects.first()
articles_qs = ArticlePage.objects.filter(trending=True).live().order_by(
"-date"
"-date", "-id"
)
# Exclude specified article IDs
@ -183,7 +183,7 @@ class HomePage(Page, CategoryMixin):
"url": category.url,
"items": ArticlePage.objects.descendant_of(category)
.live()
.order_by("-date")[:HORIZON_SIZE],
.order_by("-date", "-id")[:HORIZON_SIZE],
"layout": "horizon",
}
)
@ -305,7 +305,7 @@ class ArticlePage(Page):
.exclude(id=self.id)
.filter(tags__id__in=tag_ids)
.distinct()
.order_by("-date")[:4]
.order_by("-date", "-id")[:4]
)
else:
related_articles = ArticlePage.objects.none()

View File

@ -36,6 +36,13 @@
display: block;
}
@media (max-width: 767px) {
.home-banner {
width: 100vw;
margin-left: calc(50% - 50vw);
}
}
.list-title {
align-items: center;
margin: 10px 0;
@ -98,3 +105,26 @@
width: 142px;
}
}
@media (max-width: 574px) {
.block-title {
width: 139px;
height: 55px;
font-size: 16px;
}
.block-title span {
padding-left: 14px;
line-height: 55px;
}
.block-title-divider {
width: 20px;
height: 1px;
transform: translate(-4px, -4px);
}
.more-link {
font-size: 14px;
}
}

View File

@ -143,15 +143,11 @@
border-radius: 12px;
}
@media (min-width: 768px) and (max-width: 1023px) {
@media (min-width: 768px) and (max-width: 1023px), (max-width: 574px) {
.horizontal-list {
gap: 16px;
}
.horizontal-list li {
flex: 0 0 145px;
}
.horizontal-list-thumb {
width: 139px;
height: 114px;
@ -167,11 +163,74 @@
background-size: 139px 25px;
}
.horizontal-list .article-title {
width: 145px;
}
.horizontal-list .article-intro {
.horizontal-list a > div:nth-of-type(3) {
display: none;
}
}
@media (min-width: 768px) and (max-width: 1023px){
.horizontal-list li {
flex: 0 0 145px;
}
.horizontal-list .article-title {
width: 145px;
}
}
@media (min-width: 575px) and (max-width: 767px) {
.horizontal-list {
flex-direction: column;
gap: 16px;
overflow-x: visible;
}
.horizontal-list li {
flex: 0 0 auto;
}
.horizontal-list li a {
display: grid;
grid-template-columns: 200px 1fr;
column-gap: 16px;
row-gap: 6px;
}
.horizontal-list li a > div:nth-of-type(1) {
grid-row: 1 / span 3;
}
.horizontal-list li a > div:nth-of-type(2),
.horizontal-list li a > div:nth-of-type(3),
.horizontal-list li a > div:nth-of-type(4) {
grid-column: 2;
}
}
@media (max-width: 574px) {
.horizontal-list-arrow {
display: none;
}
.horizontal-list {
flex-wrap: wrap;
overflow-x: visible;
scroll-snap-type: none;
}
.horizontal-list li {
flex: 0 0 142px;
}
/* .horizontal-list .article-title {
width: 142px;
} */
.horizontal-list .article-title {
font-size: 16px;
}
.horizontal-list .article-date {
font-size: 12px;
}
}

View File

@ -94,7 +94,7 @@
}
.news-hero .first-news-body {
font: 12px;
font-size: 13px;
flex: 1 1 auto;
overflow: hidden;
position: relative;
@ -188,7 +188,7 @@
overflow: hidden;
}
@media (max-width: 1023px) {
@media (min-width: 575px) and (max-width: 1023px) {
.more-news {
display: grid;
grid-template-columns: 200px 1fr 1fr;
@ -246,6 +246,74 @@
}
}
@media (min-width: 575px) and (max-width: 767px) {
.news-list-items a {
display: grid;
grid-template-columns: 194px 1fr;
column-gap: 16px;
row-gap: 8px;
width: 100%;
}
.news-hero .first-news-image {
width: 426px;
}
.news-hero .first-news-image::after {
background: url("../img/picfrm_b426.png") no-repeat left bottom / cover;
background-size: 426px 25px;
}
.news-hero .first-news-image img {
width:426px;
height:260px;
}
.news-list-items a > div:nth-of-type(1) {
grid-row: 1 / span 3;
}
.news-list-items a > div:nth-of-type(2),
.news-list-items a > div:nth-of-type(3),
.news-list-items a > div:nth-of-type(4) {
grid-column: 2;
}
.more-news {
grid-template-columns: 1fr 1fr;
}
.more-news .more-news-title {
margin-bottom: 20px;
grid-column: 1 / -1;
grid-row: 1;
}
.more-news .article-title {
margin-top: 10px;
}
.more-news a:nth-of-type(1) {
grid-column: 1;
grid-row: 2;
}
.more-news a:nth-of-type(2) {
grid-column: 2;
grid-row: 2;
}
.more-news a:nth-of-type(3) {
grid-column: 1;
grid-row: 3;
}
.more-news a:nth-of-type(4) {
grid-column: 2;
grid-row: 3;
}
}
@media (min-width: 768px) and (max-width: 1023px) {
.news-hero {
grid-template-columns: 318px 1fr;
@ -276,3 +344,81 @@
gap: 16px;
}
}
@media (min-width: 575px) and (max-width: 1023px) {
.news-hero .fist-news-title {
font-size: 36px;
}
}
@media (max-width: 574px) {
.news-hero .first-news-image {
width: 300px;
height: 220px;
justify-self: center;
}
.news-hero .first-news-image::after {
background: url("../img/picfrm_b300.png") no-repeat left bottom / cover;
background-size: 300px 25px;
}
.news-hero .first-news-image img {
width: 300px;
height: 220px;
}
/* .news-hero .first-news-content {
height: 220px;
} */
.news-hero .fist-news-title {
font-size: 24px;
}
.news-hero .first-news-intro {
font-size: 16px;
}
.news-list-lower {
gap: 16px;
}
.news-list-items a {
width: 142px;
}
/* .news-list-lower {
justify-content: center;
} */
.news-list-thumb {
width: 139px;
height: 110px;
}
.news-list-thumb::after {
background: url("../img/picfrm_o139.png") no-repeat left bottom / cover;
background-size: 139px 25px;
}
.news-list-items a > div:nth-of-type(3) {
display: none;
}
.news-list-items .article-title {
font-size: 16px;
}
.news-list-items .article-date {
font-size: 12px;
}
.more-news{
max-width: 142px;
gap: 12px;
}
.more-news .article-title {
font-size: 16px;
}
}

View File

@ -1,184 +0,0 @@
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
max-width: 960px;
min-height: 100vh;
margin: 0 auto;
padding: 0 15px;
color: #231f20;
font-family: 'Helvetica Neue', 'Segoe UI', Arial, sans-serif;
line-height: 1.25;
}
a {
background-color: transparent;
color: #308282;
text-decoration: underline;
}
a:hover {
color: #ea1b10;
}
h1,
h2,
h3,
h4,
h5,
p,
ul {
padding: 0;
margin: 0;
font-weight: 400;
}
svg:not(:root) {
overflow: hidden;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e6e6e6;
}
.logo {
width: 150px;
margin-inline-end: 20px;
}
.logo a {
display: block;
}
.figure-logo {
max-width: 150px;
max-height: 55.1px;
}
.release-notes {
font-size: 14px;
}
.main {
padding: 40px 0;
margin: 0 auto;
text-align: center;
}
.figure-space {
max-width: 265px;
}
@keyframes pos {
0%, 100% {
transform: rotate(-6deg);
}
50% {
transform: rotate(6deg);
}
}
.egg {
fill: #43b1b0;
animation: pos 3s ease infinite;
transform: translateY(50px);
transform-origin: 50% 80%;
}
.main-text {
max-width: 400px;
margin: 5px auto;
}
.main-text h1 {
font-size: 22px;
}
.main-text p {
margin: 15px auto 0;
}
.footer {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
border-top: 1px solid #e6e6e6;
padding: 10px;
}
.option {
display: block;
padding: 10px 10px 10px 34px;
position: relative;
text-decoration: none;
}
.option svg {
width: 24px;
height: 24px;
fill: gray;
border: 1px solid #d9d9d9;
padding: 5px;
border-radius: 100%;
top: 10px;
inset-inline-start: 0;
position: absolute;
}
.option h2 {
font-size: 19px;
text-decoration: underline;
}
.option p {
padding-top: 3px;
color: #231f20;
font-size: 15px;
font-weight: 300;
}
@media (max-width: 996px) {
body {
max-width: 780px;
}
}
@media (max-width: 767px) {
.option {
flex: 0 0 50%;
}
}
@media (max-width: 599px) {
.main {
padding: 20px 0;
}
.figure-space {
max-width: 200px;
}
.footer {
display: block;
width: 300px;
margin: 0 auto;
}
}
@media (max-width: 360px) {
.header-link {
max-width: 100px;
}
}

View File

@ -8,12 +8,6 @@ a {
padding: 0 16px;
}
@media (max-width: 1023px) {
.site-container {
max-width: 640px;
}
}
.full-bleed {
width: 100vw;
margin-left: calc(50% - 50vw);
@ -55,6 +49,7 @@ a {
.main-nav {
flex: 1 1 auto;
margin-left: 16px;
top: 56px;
}
.main-menu {
@ -73,6 +68,82 @@ a {
text-align: left;
}
.menu-item-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.submenu-toggle {
display: none;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: 0;
background: none;
padding: 0;
cursor: pointer;
color: inherit;
}
.submenu-toggle::after {
content: "";
width: 8px;
height: 8px;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(45deg);
display: block;
transition: transform 160ms ease;
}
.menu-item.is-open .submenu-toggle::after {
transform: rotate(225deg);
}
.menu-divider {
display: none;
height: 1px;
background: currentColor;
opacity: 0.6;
margin: 8px 0 0;
}
.menu-toggle {
display: none;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 4px;
width: 32px;
height: 32px;
background: none;
border: 0;
padding: 0;
cursor: pointer;
}
.menu-toggle-bar {
width: 20px;
height: 2px;
background: currentColor;
display: block;
}
.menu-toggle.is-open .menu-toggle-bar:nth-child(1) {
transform: translateY(6px) rotate(45deg);
}
.menu-toggle.is-open .menu-toggle-bar:nth-child(2) {
opacity: 0;
}
.menu-toggle.is-open .menu-toggle-bar:nth-child(3) {
transform: translateY(-6px) rotate(-45deg);
}
.main-menu-link {
display: inline-block;
padding: 12px 4px;
@ -192,11 +263,179 @@ a {
}
@media (max-width: 1023px) {
.site-container {
max-width: 640px;
}
.header-search input[type="search"] {
width: 90px;
}
}
@media (min-width: 575px) and (max-width: 767px) {
.site-container {
max-width: 426px;
}
.site-header .site-container {
padding: 0 44px;
margin: 0;
}
.main-menu {
justify-content: flex-end;
}
.header-search input[type="search"] {
width: 163px;
}
.main-nav {
right: -28px;
}
}
@media (max-width: 767px) {
.site-header .site-container {
position: relative;
}
.header-inner {
width: 100%;
}
.main-nav {
position: absolute;
/* top: 100%; */
width: 220px;
display: none;
padding: 16px 0;
background: #0e1b42;
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
z-index: 5;
}
.main-nav.is-open {
display: block;
}
.main-menu {
flex-direction: column;
align-items: flex-start;
gap: 12px;
width: 220px;
padding: 0 16px;
}
.menu-item {
flex: 0 0 auto;
width: 100%;
text-align: left;
}
.menu-item-header {
width: 192px;
}
.menu-toggle {
display: flex;
margin-left: 12px;
color: #ffffff;
}
.template-homepage .menu-toggle {
color: #ffffff;
}
.template-homepage .main-nav {
background: #0e1b42;
}
.main-menu-link {
color: #ffffff;
font-size: 14px;
}
.submenu-toggle {
display: inline-flex;
color: #ffffff;
}
.menu-divider {
margin-left: 0;
margin-right: 0;
width: 92px;
}
.menu-item.is-open .menu-divider {
display: block;
}
.submenu {
position: static;
/* transform: none; */
margin: 8px 0 0;
opacity: 1;
visibility: visible;
pointer-events: auto;
display: none;
border: 0;
}
/* .menu-item:focus-within .submenu {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateX(-50%) translateY(2px);
} */
.menu-item.is-open .submenu {
display: block;
transform: none;
}
.submenu-item {
background: none;
border: 0;
height: auto;
}
.submenu-item a {
padding: 6px 0 6px 18px;
color: #ffffff;
font-size: 14px;
}
}
@media (max-width: 574px) {
.site-container {
max-width: 300px;
}
/* .header-inner {
padding: 16px 0;
} */
.header-inner {
flex-wrap: wrap;
}
.header-search {
width: 100%;
order: 3;
margin-left: 0;
margin-top: 12px;
}
.header-search input[type="search"] {
width: 195px;
}
.main-nav {
right: 16px;
}
}
@layer figreset {
:root {
font-family: var( --default-font-family,ui-sans-serif,system-ui,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji' )

View File

@ -0,0 +1,37 @@
document.addEventListener("DOMContentLoaded", function () {
var toggle = document.querySelector(".menu-toggle");
var nav = document.querySelector(".main-nav");
if (!toggle || !nav) {
return;
}
toggle.addEventListener("click", function () {
var isOpen = nav.classList.toggle("is-open");
toggle.classList.toggle("is-open", isOpen);
toggle.setAttribute("aria-expanded", isOpen ? "true" : "false");
});
var submenuToggles = document.querySelectorAll(".submenu-toggle");
submenuToggles.forEach(function (button) {
button.addEventListener("click", function () {
var item = button.closest(".menu-item");
if (!item) {
return;
}
var isOpen = item.classList.contains("is-open");
document.querySelectorAll(".menu-item.is-open").forEach(function (openItem) {
if (openItem !== item) {
openItem.classList.remove("is-open");
var openButton = openItem.querySelector(".submenu-toggle");
if (openButton) {
openButton.setAttribute("aria-expanded", "false");
}
}
});
item.classList.toggle("is-open", !isOpen);
button.setAttribute("aria-expanded", !isOpen ? "true" : "false");
});
});
});

View File

@ -46,6 +46,7 @@
{# Global javascript #}
<script type="text/javascript" src="{% static 'js/mysite.js' %}"></script>
<script type="text/javascript" src="{% static 'js/header.js' %}"></script>
{# Instagram embed script to render IG oEmbeds #}
<script async src="https://www.instagram.com/embed.js"></script>

View File

@ -7,45 +7,51 @@
{% if settings.base.HeaderSettings.logo_light and settings.base.HeaderSettings.logo_dark %}
<a href="/" class="logo logo--light">
{% if settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_light fill-197x28 alt=settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_light fill-217x30 alt=settings.base.HeaderSettings.site_name %}
{% else %}
{% image settings.base.HeaderSettings.logo_light fill-197x28 %}
{% image settings.base.HeaderSettings.logo_light fill-217x30 %}
{% endif %}
</a>
<a href="/" class="logo logo--dark">
{% if settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_dark fill-197x28 alt=settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_dark fill-217x30 alt=settings.base.HeaderSettings.site_name %}
{% else %}
{% image settings.base.HeaderSettings.logo_dark fill-197x28 %}
{% image settings.base.HeaderSettings.logo_dark fill-217x30 %}
{% endif %}
</a>
{% elif settings.base.HeaderSettings.logo_light %}
<a href="/" class="logo">
{% if settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_light fill-197x28 alt=settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_light fill-217x30 alt=settings.base.HeaderSettings.site_name %}
{% else %}
{% image settings.base.HeaderSettings.logo_light fill-197x28 %}
{% image settings.base.HeaderSettings.logo_light fill-217x30 %}
{% endif %}
</a>
{% elif settings.base.HeaderSettings.logo_dark %}
<a href="/" class="logo">
{% if settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_dark fill-197x28 alt=settings.base.HeaderSettings.site_name %}
{% image settings.base.HeaderSettings.logo_dark fill-217x30 alt=settings.base.HeaderSettings.site_name %}
{% else %}
{% image settings.base.HeaderSettings.logo_dark fill-197x28 %}
{% image settings.base.HeaderSettings.logo_dark fill-217x30 %}
{% endif %}
</a>
{% endif %}
<nav class="main-nav">
<ul class="main-menu">
<nav class="main-nav" id="site-nav">
<ul class="main-menu" id="main-menu">
{% with site_root=page.get_site.root_page %}
{# Top-level menu: direct children of site root #}
<li class="menu-item">
<a href="#">
<span class="main-menu-link">最新文章</span>
</a>
<div class="menu-item-header">
<a href="#">
<span class="main-menu-link">最新文章</span>
</a>
{% if nav_latest_page or nav_trending_page %}
<button class="submenu-toggle" type="button" aria-expanded="false" aria-label="Toggle submenu"></button>
{% endif %}
</div>
{% if nav_latest_page or nav_trending_page %}
<span class="menu-divider" aria-hidden="true"></span>
<ul class="submenu">
{% if nav_latest_page %}
<li class="submenu-item">
@ -66,12 +72,20 @@
</li>
{% for menu_page in site_root.get_children.live.in_menu %}
<li class="menu-item">
<a href="{{ menu_page.url }}">
<span class="main-menu-link">{{ menu_page.title }}</span>
</a>
<div class="menu-item-header">
<a href="{{ menu_page.url }}">
<span class="main-menu-link">{{ menu_page.title }}</span>
</a>
{% with submenu=menu_page.get_children.live.in_menu %}
{% if submenu %}
<button class="submenu-toggle" type="button" aria-expanded="false" aria-label="Toggle submenu"></button>
{% endif %}
{% endwith %}
</div>
{# Second-level: direct children of each top-level page #}
{% with submenu=menu_page.get_children.live.in_menu %}
{% if submenu %}
<span class="menu-divider" aria-hidden="true"></span>
<ul class="submenu">
{% for subpage in submenu %}
<li class="submenu-item">
@ -91,9 +105,11 @@
{% if settings.base.HeaderSettings.main_links %}
{% for item in settings.base.HeaderSettings.main_links %}
<li class="menu-item">
<a href="{{ item.value.url }}">
<span class="main-menu-link">{{ item.value.label }}</span>
</a>
<div class="menu-item-header">
<a href="{{ item.value.url }}">
<span class="main-menu-link">{{ item.value.label }}</span>
</a>
</div>
</li>
{% endfor %}
{% endif %}
@ -113,6 +129,12 @@
aria-label="搜尋文章">
</div>
</form>
<button class="menu-toggle" type="button" aria-expanded="false" aria-controls="site-nav" aria-label="Toggle menu">
<span class="menu-toggle-bar"></span>
<span class="menu-toggle-bar"></span>
<span class="menu-toggle-bar"></span>
</button>
</div>
</div>
</header>