我要魔改一下博客的说说样式!
忘记了是什么时候兴起的这个想法。真正促使我去实现这个想法的,是夏洛蒂的角色演示视频。传送门:《原神》角色演示-「夏洛蒂:爆炸新闻!」
她真的好可爱啊!这么活泼可爱的冰系角色,真的少见。
夏洛蒂的可爱是一方面,角色演示里面的蒸汽鸟报同样也令人在意。
虽然里面的文字我看不懂,但是看看这排版,看看这色彩,真是令人愉悦,我很喜欢。
众所周知,写代码很容易,但是美学设计是一件非常考验艺术素养的工作。彼时的我正在为说说页面的样式设计烦恼,看到这个角色演示视频,发现了新的大陆,茅塞顿开!当即决定了说说页面的样式——我要抄袭《蒸汽鸟报》。
这没什么可丢人的,反而一种学习的过程,让你无限进步。
效果展示
桌面端、移动端自适应,点击下方链接查看Demo。
实现代码
基本上重写了整个页面结构,来保证效果实现。自定义设置方面,移除了说说模板说说提示箭头
,剩下的还能用。
样式方面,主要应用Flex布局来实现效果,能够自适应桌面端和移动端。
页面模板
<?php
/**
* Template Name: 说说模版
*/
get_header();
?>
<div id="primary" class="content-area">
<main class="site-main" role="main">
<?php
$shuoshuo_per_page = iro_opt('shuoshuo_per_page'); //每页显示的说说数量
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'shuoshuo',
'post_status' => 'publish',
'posts_per_page' => $shuoshuo_per_page,
'paged' => $paged
);
$shuoshuo_query = new WP_Query($args);
?>
<div class="entry-content">
<?php the_content( '', true ); ?>
</div>
<div class="cbp_shuoshuo">
<?php if ($shuoshuo_query->have_posts()) : ?>
<ul id="main" class="cbp_tmtimeline">
<?php while ($shuoshuo_query->have_posts()) : $shuoshuo_query->the_post(); ?>
<li id="shuoshuo_post">
<div class="shuoshuo-content">
<div class="shuoshuo-text">
<div class="shuoshuo-title">
<?php the_title('<h2>', '</h2>') ?>
</div>
<div class="shuoshuo-body">
<p><?php echo strip_tags(get_the_content()) ?></p>
</div>
</div>
<div class="shuoshuo-images">
<?php
preg_match_all('/<a[^>]+><img[^>]+><\/a>|<img[^>]+\/>/i', get_the_content(), $shuoshuo_images);
$shuoshuo_images_count = count($shuoshuo_images[0]);
if (!empty($shuoshuo_images_count)) {
switch($shuoshuo_images_count) {
case 1:
$image_html_list = '<span class="image-full">'.$shuoshuo_images[0][0].'</span>';
break;
case 2:
$image_html_list = '<span class="image-two">'.$shuoshuo_images[0][0].'</span>';
$image_html_list.= '<span class="image-two">'.$shuoshuo_images[0][1].'</span>';
break;
case 3:
$image_html_list = '<span class="image-three">'.$shuoshuo_images[0][0].'</span>';
$image_html_list .= '<span class="image-three">'.$shuoshuo_images[0][1].'</span>';
$image_html_list .= '<span class="image-three">'.$shuoshuo_images[0][2].'</span>';
break;
default :
$image_html_list = '<span class="image-four">'.$shuoshuo_images[0][0].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][1].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][2].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][3].'</span>';
break;
}
} else {
$image_html_list = '<span class="image-full"><img src="' . DEFAULT_FEATURE_IMAGE() . '"/></span>';
}
remove_filter( 'the_content', 'wpautop' );
$image_html_list = apply_filters( 'the_content', $image_html_list );
echo $image_html_list;
?>
</div>
</div>
<div class="shuoshuo-meta">
<div class="shuoshuo-author-image">
<?php echo get_avatar(get_the_author_meta('ID'), 96, '','shuoShuo author img', array()) ?>
</div>
<div class="shuoshuo-author-name">
<?php echo get_the_author_meta( 'display_name' ) ?>
</div>
<div class="shuoshuo-comment-count">
<i class="fa-regular fa-comments"></i> <?php comments_number('0', '1', '%') ?>
</div>
<div class="shuoshuo-date">
<i class="fa-regular fa-clock"></i> <?php the_time('Y-m-d H:i'); ?>
</div>
<div class="shuoshuo-more">
<a href="<?php the_permalink(); ?>">
<i class="fa-solid fa-angles-right fa-beat"></i> <?php _e('View Idea','sakurairo') ?>
</a>
</div>
</div>
<div class="shuoshuo-feather">
<i class="fa-solid fa-feather fa-flip-horizontal fa-2xl"></i>
</div>
</li>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>
</ul>
<?php else : ?>
<h3 style="text-align: center;">
<?php _e('You have not posted a comment yet', 'sakurairo') ?>
</h3>
<p style="text-align: center;">
<?php _e('Go and post your first comment now', 'sakurairo') ?>
</p>
<?php endif; ?>
</div>
</main><!-- #main -->
<?php if (iro_opt('pagenav_style') == 'ajax') { ?>
<div id="pagination">
<?php next_posts_link(__('Load More', 'sakurairo'), $shuoshuo_query->max_num_pages); ?>
</div>
<div id="add_post">
<span id="add_post_time" style="visibility: hidden;" title="<?php echo iro_opt('page_auto_load', ''); ?>"></span>
</div>
<?php } else { ?>
<nav class="navigator">
<?php previous_posts_link('<i class="fa-solid fa-angle-left"></i>') ?>
<?php next_posts_link('<i class="fa-solid fa-angle-right"></i>', $shuoshuo_query->max_num_pages) ?>
</nav>
<?php } ?>
</div>
<?php get_footer(); ?>
/*说说模板样式-起*/
#shuoshuo_post {
display: flex;
flex-direction: column;
max-width: 100%;
height: 400px;
margin-bottom: 32px;
padding: 20px;
border: 3px solid var(--shuoshuo_background_color1);
box-shadow: -4px 4px 0px 0px var(--shuoshuo_background_color2);
background: linear-gradient(to bottom right, var(--shuoshuo_background_color1), var(--shuoshuo_background_color2));
transition: all 0.5s ease-in-out;
}
#shuoshuo_post:hover {
box-shadow: 0 0 20px 2px var(--shuoshuo_background_color2);
transition: all 0.5s ease-in-out;
}
#shuoshuo_post:nth-child(even) {
border: 3px solid var(--shuoshuo_background_color2);
box-shadow: -4px 4px 0px 0px var(--shuoshuo_background_color1);
background: linear-gradient(to bottom right, var(--shuoshuo_background_color2), var(--shuoshuo_background_color1));
transition: all 0.5s ease-in-out;
}
#shuoshuo_post:nth-child(even):hover {
box-shadow: 0 0 20px 2px var(--shuoshuo_background_color1);
transition: all 0.5s ease-in-out;
}
.shuoshuo-content {
display: flex;
height: 355px;
}
#shuoshuo_post:nth-child(even) .shuoshuo-content {
flex-direction: row-reverse;
}
.shuoshuo-text {
display: flex;
flex-direction: column;
width: 30%;
height: 355px;
margin-right: 15px;
padding: 10px;
border: 2px solid var(--shuoshuo_background_color1);
}
#shuoshuo_post:nth-child(even) .shuoshuo-text {
margin: 0 0 0 15px;
border: 2px solid var(--shuoshuo_background_color2);
}
.shuoshuo-title {
flex-shrink: 0;
font-size: 1rem;
line-height: 2rem;
text-align: center;
margin-bottom: 12px;
max-height: 150px;
overflow: hidden;
}
.shuoshuo-title h2 {
margin: 0;
}
.shuoshuo-title h2::before {
display: none;
}
.shuoshuo-body::-webkit-scrollbar {
width: 1px;
}
.shuoshuo-body::-webkit-scrollbar-thumb, #shuoshuo_post:nth-child(even) .shuoshuo-body::-webkit-scrollbar-track {
background-color: var(--shuoshuo_background_color1);
}
.shuoshuo-body::-webkit-scrollbar-track, #shuoshuo_post:nth-child(even) .shuoshuo-body::-webkit-scrollbar-thumb {
background-color: var(--shuoshuo_background_color2);
}
.shuoshuo-body {
flex-grow: 1;
overflow-y: auto;
overflow-x: overlay;
}
.shuoshuo-body p {
margin: 0 0 0.5rem;
word-break: break-all;
}
.shuoshuo-images {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
width: 70%;
height: 355px;
padding: 0.6%;
border: 2px solid var(--shuoshuo_background_color1);
overflow: hidden;
}
#shuoshuo_post:nth-child(even) .shuoshuo-images {
border: 2px solid var(--shuoshuo_background_color2);
}
.shuoshuo-images span {
display: block;
overflow: hidden;
}
.shuoshuo-images img {
object-fit: cover;
object-position: center;
height: 100%;
margin: 0;
padding: 0;
width: 100%;
transition: all 0.3s ease-in-out;
}
.shuoshuo-images img:hover {
transform: scale(1.1);
transition: all 0.3s ease-in-out;
}
.shuoshuo-images .image-full {
width: 100%;
height: 100%;
}
.shuoshuo-images .image-four {
width: 49.2%;
height: 49.2%;
}
.shuoshuo-images .image-four:nth-child(1) {
margin: 0 0.3% 0.3% 0;
}
.shuoshuo-images .image-four:nth-child(2) {
margin: 0 0 0.3% 0.3%;
}
.shuoshuo-images .image-four:nth-child(3) {
margin: 0.3% 0.3% 0 0;
}
.shuoshuo-images .image-four:nth-child(4) {
margin: 0.3% 0 0 0.3%;
}
.shuoshuo-images .image-three {
width: 49.2%;
height: 55%;
}
.shuoshuo-images .image-three:last-child {
width: 100%;
height: 44%;
}
.shuoshuo-images .image-three:nth-child(1) {
margin: 0 0.3% 0.3% 0;
}
.shuoshuo-images .image-three:nth-child(2) {
margin: 0 0 0.3% 0.3%;
}
.shuoshuo-images .image-three:nth-child(3) {
margin: 0.3% 0 0 0;
}
.shuoshuo-images .image-two {
width: 49.2%;
height: 100%
}
.shuoshuo-images .image-two:nth-child(1) {
margin-right: 0.3%;
}
.shuoshuo-images .image-two:nth-child(2) {
margin-left: 0.3%;
}
.shuoshuo-meta {
display: flex;
align-items: center;
justify-content: right;
font-size: 12px;
padding: 0 0 0 30px;
}
#shuoshuo_post:nth-child(even) .shuoshuo-meta {
justify-content: left;
padding: 0px 30px 0 0;
}
.shuoshuo-author-image {
height: 16px;
width: 16px;
margin-right: 5px;
}
.shuoshuo-author-name, .shuoshuo-comment-count, .shuoshuo-date {
margin-right: 10px;
}
.shuoshuo-more a {
color: currentColor;
}
.shuoshuo-author-image img {
height: 100%;
width: auto;
}
.shuoshuo-feather {
display: flex;
position: relative;
left: -18px;
top: -25px;
font-size: 24px;
}
.shuoshuo-feather i {
color: var(--shuoshuo_background_color1)
}
#shuoshuo_post:nth-child(even) .shuoshuo-feather {
flex-direction: row-reverse;
left: auto;
right: -18px;
}
#shuoshuo_post:nth-child(even) .shuoshuo-feather i {
transform: scaleY(1);
color: var(--shuoshuo_background_color2)
}
body.dark #shuoshuo_post {
color: #505050;
}
@media (max-width: 700px) {
#shuoshuo_post {
padding-bottom: 0;
height: auto;
}
.shuoshuo-content,#shuoshuo_post:nth-child(even) .shuoshuo-content {
flex-direction: column;
height: auto;
}
.shuoshuo-text, #shuoshuo_post:nth-child(even) .shuoshuo-text {
width: 100%;
height: auto;
margin: 0 0 15px 0;
border: none;
}
.shuoshuo-images, #shuoshuo_post:nth-child(even) .shuoshuo-images {
aspect-ratio: 4/3;
width: 100%;
height: auto;
}
.shuoshuo-meta {
justify-content: left;
padding: 0 30px 0 0;
flex-wrap: wrap;
}
.shuoshuo-feather {
flex-direction: row-reverse;
left: auto;
right: -18px;
}
.shuoshuo-feather i {
transform: scaleY(1);
}
}
/*说说模板样式-止*/
代码解析
说说标题
<div class="shuoshuo-title">
<?php the_title('<h2>', '</h2>') ?>
</div>
the_title('<h2>', '</h2>')
函数会获取每篇说说的标题,并自动添加二级标题标签。从SEO优化的角度上来看,一个页面最好只有一个一级标题,所以这里选择了应用二级标题。
说说内容
值得一提的是,在设计上,说说的内容分为两个部分:文本内容、图片。换句话说,只支持输出纯文本内容和图片。鉴于视频播放的各种千奇百怪实现方式,把它们输出到说说页面上,需要做的适配性工作太多了,故一刀切,只显示文本和图片。
输出文本
<div class="shuoshuo-body">
<p><?php echo strip_tags(get_the_content()) ?></p>
</div>
上面的代码,是输出说说内容之一的文本内容,说说里面任何HTML标签都会被移除。有一个需要注意的地方是,get_the_content()
函数不会应用the_content
过滤器,这意味着你挂载在the_content
钩子上的任何函数都不会生效,会导致一些诸如纯文本替换、表情实现等通过后端实现的功能失效。
如果你有上诉需求,可以修改为下面的代码,以应用the_content
过滤器。
<div class="shuoshuo-body">
<?php
$shuoshuo_content = apply_filters( 'the_content', get_the_content() );
echo strip_tags($shuoshuo_content)
?>
</div>
输出图片
preg_match_all('/<img[^>]+\/>/i', get_the_content(), $shuoshuo_images);
$shuoshuo_images_count = count($shuoshuo_images[0]);
使用preg_match_all
函数提取说说内容里面的所有图片,存储在数组中,并获取图片总数量。正则表达式/<img[^>]+\/>/i
会匹配说说内容里的所有<img>
标签。
switch($shuoshuo_images_count) {
case 1:
$image_html_list = '<span class="image-full">'.$shuoshuo_images[0][0].'</span>';
break;
case 2:
$image_html_list = '<span class="image-two">'.$shuoshuo_images[0][0].'</span>';
$image_html_list.= '<span class="image-two">'.$shuoshuo_images[0][1].'</span>';
break;
case 3:
$image_html_list = '<span class="image-three">'.$shuoshuo_images[0][0].'</span>';
$image_html_list .= '<span class="image-three">'.$shuoshuo_images[0][1].'</span>';
$image_html_list .= '<span class="image-three">'.$shuoshuo_images[0][2].'</span>';
break;
default :
$image_html_list = '<span class="image-four">'.$shuoshuo_images[0][0].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][1].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][2].'</span>';
$image_html_list .= '<span class="image-four">'.$shuoshuo_images[0][3].'</span>';
break;
}
从样式美观的角度上考虑,同时也为了减少工作量,这里设计了最多显示4张图片。如果说说内容里的图片大于4张。则只会显示前4张图片。
else {
$image_html_list = '<span class="image-full"><img src="' . DEFAULT_FEATURE_IMAGE() . '"/></span>';
}
如果说说内容里没有图片,为了保证样式的同一,会从与首页封面图片相同的来源加载一张图片用作装饰。
function DEFAULT_FEATURE_IMAGE(string $size='source'):string
{
if (iro_opt('post_cover_options') == 'type_2') {
return get_random_url(iro_opt('post_cover'));
}
if (iro_opt('random_graphs_options') == 'external_api'){
return get_random_url(iro_opt('random_graphs_link'));
}
$_api_url = rest_url('sakura/v1/image/feature');
$rand = rand(1, 100);
# 拼接符
$splice = strpos($_api_url, 'index.php?') !== false ? '&' : '?';
$_api_url = "{$_api_url}{$splice}size={$size}&$rand";
return $_api_url;
}
关于DEFAULT_FEATURE_IMAGE()
函数的更多内容,可以看看上边的函数原型。
remove_filter( 'the_content', 'wpautop' );
$image_html_list = apply_filters( 'the_content', $image_html_list );
echo $image_html_list;
最后是对构建好的图片内容使用the_content
过滤器,主要用于图片灯箱的支持。别忘了在应用the_content
过滤器之前移除wpautop
函数,它会在内容中自动添加<p>
标签,这会造成样式错误。
说说元数据
包括:作者头像、作者名称、评论数量、发布时间和“查看说说”超链接,采用fontawesome 图标装饰。
<div class="shuoshuo-meta">
<div class="shuoshuo-author-image">
<?php echo get_avatar(get_the_author_meta('ID'), 96, '','shuoShuo author img', array()) ?>
</div>
<div class="shuoshuo-author-name">
<?php echo get_the_author_meta( 'display_name' ) ?>
</div>
<div class="shuoshuo-comment-count">
<i class="fa-regular fa-comments"></i> <?php comments_number('0', '1', '%') ?>
</div>
<div class="shuoshuo-date">
<i class="fa-regular fa-clock"></i> <?php the_time('Y-m-d H:i'); ?>
</div>
<div class="shuoshuo-more">
<a href="<?php the_permalink(); ?>">
<i class="fa-solid fa-angles-right fa-beat"></i> <?php _e('View Idea','sakurairo') ?>
</a>
</div>
</div>
一个装饰品
《蒸汽鸟报》页面中采用了一个相机作为饰品,我搜寻好久,没有找到合适的相机样式。几经辗转,找到了一个看起来还可以的,但是SVG格式需要付费下载,我付不起。没有SVG格式的图片,不好进行颜色自适应更改,遂放弃。
看电影的时候突然找到了灵感:一支羽毛制成的笔,意为记录时间。
使用方法
不知道这个样式是否会被主题采纳,现阶段你可以通过以下方法应用它。
-
将主题
page-word.php
文件里的代码全部替换为前述的页面模板代码 -
在主题
style.css
文件里的末尾加入前述的CSS代码 -
删除
style.css
文件里下面内容:.cbp_tmtimeline:before { content: ''; position: absolute; top: 0; bottom: 0; width: 4px; background: RGBA(0, 0, 0, 0.02); left: 80px; margin-left: 10px; }
从节省网络资源的角度上考虑,你应该还需删除旧的说说页面样式,具体的删除内容,请参考我的github推送。
Comments 7 条评论
博主 ZI-Lan
大佬,我按你文章内容操作了但是不知道哪里错了,页面并没有效果,这是我改过的php和css文件,如果大佬有时间的话,能不能帮我瞅一眼,万分感谢 ,属于是搬都搬不明白了 ,现在界面是这个样子.
博主 Kano酱
@ZI-Lan 使用方法不对噢,你应该建立一个独立页面,模板选择说说模板,所有说说就会显示在独立页面里了
博主 ZI-Lan
博主,我点击你那个说说demo会显示已登录,虽然点击管理后台被拒绝了,但应该还是挺危险的?不太懂这个有没有什么危险,还是提醒一下
(`・ω・´)
博主 Kano酱
@ZI-Lan 大丈夫~感谢你的提醒噢
博主 ZI-Lan
@Kano酱 哈哈哈,不客气,谢谢Kano的分享,最近也在学着搭网站,完全纯萌新,全靠搬运各位大佬的代码哈哈,我不生产代码,我只是代码的搬运工
博主 毒蛊博客
真好看
博主 Kano酱
@毒蛊博客 啊哈,献丑了