用Gatsby和Strapi创建一个静态博客

本文以简单通俗的方式讲解了结合Gatsby和Strapi创建一个静态博客的方法和具体步骤, 也额外插入了许多创建过程中遇到的各种问题和解决办法.

原文参阅: Building a static blog using Gatsby and Strapihttps://blog.strapi.io/buildi…. 本篇首发在SegmentFault上, 用Markdown语法, 所以美观性相比更强. 本篇主要是对原文精华内容进行翻译, 以及实操过程中遇到的问题解决和探索. 一些具体的操作步骤和细节, 我将忽略, 结合原文一起阅读效果更佳!

注: 本文操作环境是Linux VPS, CentOS 6 64bit

介绍

这是一个包含很多静态内容页面的站点, 从技术上来说就如同一系列HTML文件, 展示给访问者. 与动态网站不同的是, 他不需要后端开发或者数据库支撑. 发布静态站点之所以容易, 是因为文件只需要上传到服务器或者存储器. 没有额外的渲染页面的请求, 也没有数据库被黑的风险, 所以它既安全也快速.

为了快速建站, 其实很多开源的静态页面生成框架可用, 比如前阵子我搞的Jekyll, Hugo, 好似国人偏爱的Hexo等等, 他们的工作原理相似, 内容都是通过静态文件(比如Markdown)或者带有内容的API, 通过获取这些内容, 注入到开发者做好的模板, 最后生成一大堆HTML文件.

Progressive Web Apps (PWA)实际上是网页应用, 几乎基于Javascript, 并且可靠, 快速, 有吸引力的. 这几年比较火的Angular, Vue, React都是类似的前端框架.

静态站点遇见了PWA就产生了Gatsby

将这两点组合起来的最佳选择看起来就是Gatsby了, 但是同样需要一个内容接口, 这就是我将要展示的, 通过Strapi创建一个内容API提供给Gatsby, 然后打包发布出一个静态站点.


Gatsby是什么

这个并不是型男熟知的杰士派, 虽然我也用过这个发泥, 好像不是很好用. Gatsby是基于React的快速静态网站框架, 有了它, 你就可以感觉飘飘然的开发React网站了.

Strapi是什么

Strapi是一个基于高级的Nodejs API内容管理框架. 听起来有点绕口, 通俗来说就是让你能简单, 安全, 高效的开发出强大API的开源的内容管理框架. 它是免费的, 人们都爱免费的, 可以随意在你的服务器上使用, 也非常具有可个性化, 可扩展性的玩意.

我真想不到国内几乎没有人用Gatsby和Strapi, 百度上查不到任何资料…

创建API

见证奇迹的时刻即将到来, 我们快创建个Strapi API, 添加点内容吧!

创建Strapi项目

Requirements: please make sure Node 8 (or higher) and MongoDB are installed and running on your machine.

此时, 暗喜前阵子已经琢磨出来了并装好了Node 8, 不过装MongoDB就没有了. 因此这里就要插入一段关于MongoDB的内容了. 如果已经有了请自动跳过此内容.

MongoDB安装及相关问题

果断找到文档Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux, 这个redhat和centOS应该是通用的吧- -! 看到Configure the package management system (yum)., 发现原来还有这种操作, 创建repo文件, 来安装对应版本的软件. 闲话少说, 直接上代码:

# cd /etc/yum.repos.d/
# touch mongodb-org-3.6.repo
# vi mongodb-org-3.6.repo

将以下内容copy进去保存

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

再进行安装

# sudo yum install -y mongodb-org

如果有特殊需求, 请参阅上文提到的官方文档, 我这里装的是MongoDB Community Edition

按以上步骤很快就装好了. 接下来启动mongod(如果没有启动的话), 如下命令:

# service mongod start

完成后, 我们接着创建Strapi项目的主题, 推荐安装strapi@alpha版本:

# npm i strapi@alpha -g

完成后, 去到你要创建本文项目的目录, 比如我这里的路径是/home/web/, 我在这里创建一个gatsby-strapi-tutorial目录:

# mkdir gatsby-strapi-tutorial

在这里面搭一个API脚手架

# cd gatsby-strapi-tutorial
# strapi new api

进入项目目录, 并运行Node.js服务器

# cd api
# strapi start

遇到了一些小问题

这里突然时不时卡住了, 如果你很顺利, 那么可以跳过此内容, 频繁报错如下

[root@whidy api]# strapi start
DEBUG (24910 on whidy): Server wasn't able to start properly.
ERROR (24910 on whidy): (hook:mongoose) takes too long to load

大概是网络原因, 我联通网络出问题, 换了电信几番尝试就好了.

操作过程中频繁出现刚才的问题, 我觉得不是网络问题那么简单, 我打算从数据库方面着手完善一下试试, 当然后来证明, 一切问题都与MongoDB无关, 所以下面缩进内容可以选择性阅读大多数情况下我是不愿意理睬WARNING信息的, 只要不是ERROR就好, 但是这次我有点不爽, 后来折腾了半天发现有的很难处理, 好吧我错了, 我想我还是不死磕了吧😱.

  • soft rlimits too low
    WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.

    参阅:

  • versions of RHEL older than RHEL6
    WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

    服务器硬件限制? 可以安全忽略.

    参阅: WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

  • Access Control
    以为要搞账户什么的, 然后运行mongo命令, 创建了一个admin账户:

    # mango
    > use admin
    > db.createUser(
        {
          user: "username",
          pwd: "userpassword",
          roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
      )
    # mongo --port 27017 -u "username" -p "userpassword" --authenticationDatabase "admin"

    其实我自己当时也不知道是搞啥, 其实完全没关系的操作. 很多人甚至官方文档Start MongoDB without access control.也提到:

    mongod --port 27017 --dbpath /data/db1

    可是我一直报错, 要么说不存在, 搞半天才明白, 要手动创建, 创建好了, 又说服务被占用, service mongod stop停了服务, 连上去了, show dbs发现跟之前的又不一样, 没有找到我之前看到的strapi库, 才恍然大悟, 原来其实我创建了一个跟之前无关的库…

    事实上, 启动mongod服务的时候, 它连接了一个默认配置库, 这个库的路径时早就创建好的, 通过查看/etc/mongod.conf这个文件就知道了. 因此删了那个没用的db目录. 接着操作.

    后来第二天早上, 再次执行strapi start很顺利. 我也没办法再研究昨天究竟是为什么总是连不上了. 反正就是渣渣网络经常会带来各种坑!😡, 这段没什么作用的内容就过去了.

回到刚才strapi start, 成功之后, 我们如果是本地操作的, 带有界面的操作系统的话就可以直接访问http://localhost:1337/admin了, 如果也是远程操作, 就改成IP就好了.

接下来的操作是创建用户, 原文已经图文并茂, 傻子都能看懂的步骤了, 由于篇幅过大, 我就简单翻译一下, 不详细复述了嘿嘿~

按照原文操作:

  1. 创建管理员账号(Create your first User)
  2. 创建内容类型(Create a Content Type)
    名为article的内容类型有三个字段: title(字符串), content(文本), author(关系, 多文章对应一个用户).
  3. 添加几项内容到数据库
    1. 访问文章列表页
    2. 点击Add New Article
    3. 插入值, 连接对应的作者并保存
    4. 重复以上操作, 创建额外两篇文章
  4. 允许API权限, 依原文对应勾选保存

完成后, 就可以访问http://localhost:1337/article了.

创建静态站

到目前, 你的API搞定了, 我们要搞静态网站啦

安装Gatsby

首先, 全局安装Gatsby CLI:

# npm install --global gatsby-cli

生成Gatsby项目

回到之前提到的gatsby-strapi-tutorial目录, 创建一个新博客:

# gatsby new blog

事情总是不是那么顺利.

报错, 需要git. 然而我的这台崭新的服务器还没装, 那就装一个吧.

如果你的git已经部署OK, 并且上面这个操作没有问题, 以下内容可忽略:

参考Download for Linux and Unix执行:

# yum install git

再次执行后依旧报错(当前git版本1.7.1)

error Command failed: git clone git://github.com/gatsbyjs/gatsby-starter-default.git blog --single-branch

推测是版本问题. 只好手动安装了. 于是又找到这个安装 Git

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# wget https://www.kernel.org/pub/software/scm/git/git-2.16.1.tar.gz
# tar -zxf git-2.16.1.tar.gz
# cd git-2.16.1
# make prefix=/usr/local all
# sudo make prefix=/usr/local install

漫长的make prefix=/usr/local all之后, 提示:

    SUBDIR perl
/usr/bin/perl Makefile.PL PREFIX=\'/usr/local\' INSTALL_BASE=\'\' --localedir=\'/usr/local/share/locale\'
Can\'t locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.
BEGIN failed--compilation aborted at Makefile.PL line 3.
make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2

蛋疼, 等了半天, 又要解决这个问题, 好在看起来比较容易处理, 参考git fails to build in Fedora 14, 然后继续执行最后两条make命令, 虽然最后出来很多看起来很奇怪的内容, 不过似乎是成功了. 执行:

# git --version
git version 2.16.1

接下来我们再一次执行gatsby new blog, 我擦还提示刚才的...single-branch的error, 这就坑爹了- -. 经过简短的排查. 原来似乎他还是跑的旧版git, 需要删掉之前yum自动安装的git 1.7.1, 我单纯的以为直接自动升级了. 于是:

# yum remove git

按照提示删除成功后, 再次检测git还是ok的, 这次我第三次执行gatsby new blog, 终于成功了!

我这小白也不知道linux软件管理是咋整的. 反正能继续执行卡了我半天的gatsby就好了吧…每次创建速度很慢, 执行gatsby new blog完成的时候提示added 1398 packages in 137.652s, 大概就是2分钟多, 可能是安装依赖包费时吧

启动开发模式

创建成功后, 接着操作, 进入博客目录

# cd blog

启动服务器

# gatsby develop

理论上你就可以通过http://localhost:8000访问到默认的效果博客站点了.

然而又一次出现小插曲, 如果你是和我一样远程访问, 也许以下内容对你有用

每次执行gatsby develop的时间甚至更长, 完成时提示如下:

info bootstrap finished - 334.876 s

DONE  Compiled successfully in 90373ms 21:15:06


You can now view gatsby-starter-default in the browser.

http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema

http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use gatsby build

大概用了6分钟左右, 糟糕的是并不能通过远程IP来访问! 查看了目录下的配置文件和官方文档, 也没查到. 绝望之时, 突然在大量资料中看到webpack也有这样的问题, 想起来之前webpack的server默认配置也是无法通过ip访问, 但是webpack的devServer配置host: "0.0.0.0"即可, 试了下:

# gatsby develop --host 0.0.0.0

又经过4分钟左右漫长等待, 这次成功了! 不过我尝试搜索Gatsby究竟用的什么服务器启动, 为何不能像webpack那样加一段配置呢, 却没有找到. 后来凑巧找到了一篇webpack下的issue, Server can’t be accessed via IP, 有人提到过这条命令.

因此, 从小插曲中来看, 远程访问控制的开发者, 需要加个参数, 具体命令:

# gatsby develop --host 0.0.0.0

这样, 至此开发模式服务器搞定.

安装Strapi插件(Install the Strapi source plugin)

Gatsby understands this pretty well. So its creators decided to build a specific and independent layer: the data layer. This entire system is strongly powered by GraphQL.

前面有一些插件介绍不多说了, 执行安装:

# npm install --save gatsby-source-strapi

完成后, 需要做些配置, 修改gatsby-config.js文件, 替换成以下内容:

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-strapi`,
      options: {
        apiURL: `http://localhost:1337`,
        contentTypes: [ // List of the Content Types you want to be able to request from Gatsby.
          `article`,
          `user`
        ]
      },
    },
  ],
}

保存后, 重启Gatsby服务器

文章列表

为了在首页显示文章列表, 我们需要修改首页代码如下:

路径: src/pages/index.js

import React from 'react'
import Link from 'gatsby-link'
const IndexPage = ({ data }) => (
  <div>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <ul>
      {data.allStrapiArticle.edges.map(document => (
        <li key={document.node.id}>
          <h2>
            <Link to={`/${document.node.id}`}>{document.node.title}</Link>
          </h2>
          <p>{document.node.content}</p>
        </li>
      ))}
    </ul>
    <Link to="/page-2/">Go to page 2</Link>
  </div>
)
export default IndexPage
export const pageQuery = graphql`
  query IndexQuery {
    allStrapiArticle {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`

这里就应用到了GraphQL啦, 好激动呢. 我们导出pageQuery, 一个GraphQL查询会请求文章列表, 我们只需要将需要查询的字段添加进去就好了~

然后我们传递{ data }这个结构对象作为IndexPage参数, 遍历它的allStrapiArticles对象, 来展示数据.

GraphQL查询可以快速生成, 你可以尝试在http://localhost:8000/___graphql修改, 并测试.

文章页

首页有了列表之后, 我们还要访问文章页面呢, 接下来写一个模板:

路径: src/templates/article.js

import React from 'react'
import Link from 'gatsby-link'
const ArticleTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiArticle.title}</h1>
    <p>by <Link to={`/authors/${data.strapiArticle.author.id}`}>{data.strapiArticle.author.username}</Link></p>
    <p>{data.strapiArticle.content}</p>
  </div>
)
export default ArticleTemplate
export const query = graphql`
  query ArticleTemplate($id: String!) {
    strapiArticle(id: {eq: $id}) {
      title
      content
      author {
        id
        username
      }
    }
  }
`

你需要手动创建这个目录和文件, 当然Gatsby并不知道模板何时展示. 每篇文章都需要一个特别的URL, 感谢Gatsby提供的createPage函数.

首先, 我们写个makeRequest函数来处理GraphQL请求. 然后通过createPage函数使我们在获取的文章列表后为它们创建一个页面, 路径为文章id的URL, 回到blog目录, 修改gatsby-node.js文件

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Query for articles nodes to use in creating pages.
  return getArticles;
};

再次重启Gatsby服务器.

现在你就能通过点击首页的文章进入到文章内容页面了.

作者页

虽然这个似乎并不重要, 不过还是加上学习一下吧😁

添加作者页和创建文章页很相似, 我们还是先创建个模板:

路径: src/templates/user.js

import React from 'react'
import Link from 'gatsby-link'
const UserTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiUser.username}</h1>
    <ul>
      {data.strapiUser.articles.map(article => (
        <li key={article.id}>
          <h2>
            <Link to={`/${article.id}`}>{article.title}</Link>
          </h2>
          <p>{article.content}</p>
        </li>
      ))}
    </ul>
  </div>
)
export default UserTemplate
export const query = graphql`
  query UserTemplate($id: String!) {
    strapiUser(id: { eq: $id }) {
      id
      username
      articles {
        id
        title
        content
      }
    }
  }
`

然后再次修改gatsby-node.js来创建作者URLs:

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for article nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});

// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  const getAuthors = makeRequest(graphql, `
    {
      allStrapiUser {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each user.
    result.data.allStrapiUser.edges.forEach(({ node }) => {
      createPage({
        path: `/authors/${node.id}`,
        component: path.resolve(`src/templates/user.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Queries for articles and authors nodes to use in creating pages.
  return Promise.all([
    getArticles,
    getAuthors,
  ])
};

重启服务器, 刷新页面, Wow! 大功告成! 时不时很酷!!!

原文总结

恭喜, 你成功的创建了一个超快的很好维护的博客! 然后各种夸奖Blabla

接下来做什么呢? 你可以去更多的挖掘Gatsby和Strapi的各种优点, 你可以试着增加这些功能:

  • 作者列表
  • 文章分类
  • 用Strapi API创建评论系统, 或者直接用Disqus
  • 当然你也可以试着搞其他站点, 例如电商站, 企业站等等

当然为了进一步方便开发, 你可能需要一个方便的发布在网上的存储载体, Blablabla…

本教程GitHub源码地址, 你可以clone下来, 运行npm run setup, blablabla… 我是个爱研究的人, 我要一步步操作, 才不要clone.

个人总结

这次通过Gatsby和Strapi搭建一个简单的博客站点, 还是挺不容易的, 总共花了将近两天的时间. 不过个人感觉还是值得的! 其中有很多地方是可以更加深入的学习和了解的, 这也算初步接触了react, mongodb, graphQL等相关知识实操, 同时也可以在后期完善更多的功能, 了解并学习一些ES6, 模板的写法技巧等等. 也希望通过此次研究以后能更进一步熟悉其他框架, 数据库, 后端等思想~

相关参阅汇总

最后打个小广告, 我有个GitHub项目, 用于记录我每天学习或者瞎折腾的技术, 范围不限, 有兴趣可以star我的whidy daily

如何让元素水平居中于动态宽度页面或容器中

现如今,自适应窗口的页面布局已经十分常见了,那么不同的显示器,不同的人群可能在查看页面时的显示效果必然不会相同.为了保证风格整体一致,那么在一个动态变化宽度的页面或容器中,元素居中将被常常用到.这里我并不是简简单单的给div加上一个text-align:center;属性后,其单独的块级子元素(例如img)自动居中,这种方法估计人人皆知.我将用另一个办法解决这个问题,例如子元素内比较复杂的导航条等等.这里我就以导航条的居中为例.

先来看看相关效果:

http://jsfiddle.net/kingterrors/AqTJV/embedded/result,html,css/

PS:由于近日(2014年6月)jsfiddle无法正常访问,可能受内网影响,现将之前所有jsfiddle预览去除,不过你仍然可将以上地址拷贝到浏览器预览,或选择尝试以下代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Horizontally center elements of a dynamic width</title>
<style type="text/css">
ul {display:table;margin:10px auto;min-width:320px;}
li {float:left;list-style:none;margin-left:5px;padding:5px 0;}
li:first-child { margin-left:0;}
li a {background:#82B5DA;border:1px solid #599CCE;border-radius:3px;box-shadow:0 0 3px rgba(0,0,0,0.3);padding:5px;color:#333;text-decoration:none;text-shadow:1px 1px 0 rgba(255,255,255,0.3);}
li a:hover { background:#599CCE;}
</style>
</head>
<body>
<ul>
  <li><a href="#">Home</a></li>
  <li><a href="#">Blog</a></li>
  <li><a href="#">Tutorials</a></li>
  <li><a href="#">About whidy</a></li>
</ul>
</body>
</html>

如果点了CSS查看,大家会发现这里用了display: table;这个估计很少会有人用,而且它有个很大的问题,就是这种居中的方式仅仅支持IE8+,那么IE7-不是悲剧了.因此,这里又提供一个更好的方案:

http://jsfiddle.net/kingterrors/AgxR5/embedded/result,html,css/

PS:由于近日(2014年6月)jsfiddle无法正常访问,可能受内网影响,现将之前所有jsfiddle预览去除,不过你仍然可将以上地址拷贝到浏览器预览,或选择尝试以下代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Horizontally center elements of a dynamic width</title>
<style type="text/css">
ul {margin-top:10px;text-align:center;min-width:330px;}
li {display:inline-block;list-style:none;margin-left:5px;padding:5px 0;}
li:first-child {margin-left:0;}
li {background:#82B5DA;border:1px solid #599CCE;border-radius:3px;box-shadow:0 0 3px rgba(0,0,0,0.3);padding:5px;color:#333;}
li:hover {background:#599CCE;}
li a {color:#333;text-decoration:none;text-shadow:1px 1px 0 rgba(255,255,255,0.3);}
li {*display:inline;zoom:1;}
</style>
</head>
<body>
<ul>
  <li><a href="#">Home</a></li>
  <li><a href="#">Blog</a></li>
  <li><a href="#">Tutorials</a></li>
  <li><a href="#">About whidy</a></li>
</ul>
</body>
</html>

这里有几点需要说明的是,块级元素前面已经提到是可以直接用text-align:center;居中的,而内联的也就是含有浮动的块级元素怎么处理呢,IE7对这个内联块级支持仍然不是很好.那么我们还要给li元素增加一个inline-block. zoom: 1;这样IE7就能很好的工作了.IE6好像还有点问题,那么就让IE 6 去shit吧.

总结:这是一个十分简单的关于动态宽度的页面或容器内元素自动居中的例子,我也参考过其他网友的方法,比如利用父子关系的定位,父级元素相对定位,子级元素按照百分比绝对定位的方法,不过个人感觉过于复杂,大部分情况下如果采用此文的方法也许会更好些.当然,面对不同的情景,大家也就根据自己需要进行选择了.

参考文章:http://css-plus.com/2012/05/how-to-horizontally-center-elements-of-a-dynamic-width/

如何为第一个或最后一个元素甚至是某类规律元素添加样式?

有时候,我们在写DIV+CSS的时候,在某一类相同的元素内想给其中的第一个元素或者最后一个元素,甚至是其中某些特定的有规则的排列的元素添加特别的CSS样式,我们该如何下手?下面我将给大家将就一些在CSS中十分实用的方法.

首先,你可以手动使用下面这段代码来应用修改某个元素的效果(当然这个办法很笨,是个人都知道):

http://jsfiddle.net/kingterrors/szCM9/embedded/result,html,css/

PS:由于近日(2014年6月)jsfiddle无法正常访问,可能受内网影响,现将之前所有jsfiddle预览去除,不过你仍然可将以上地址拷贝到浏览器预览,或选择尝试以下代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>how to remove margins for first last elements</title>
<style type="text/css">
ul {
    border: 1px solid #000;
    margin: 0;
    padding: 0;
    list-style: none;
    float:left;
}
ul li {
    background:#eee;
    color: #F00;
    margin: 50px;
}
.first {
    color: #000;
    margin-top: 0 !important;
    margin-left: 0 !important;
}
.last {
    color: #0f0;
    margin-bottom: 0 !important;
    margin-right: 0 !important;
}
</style>
</head>
<body>
<ul>
  <li class="first">Hello, This is first element</li>
  <li>WOW, so many elements</li>
  <li>WOW, so many elements</li>
  <li>WOW, so many elements</li>
  <li class="last">Here it is, The last element</li>
</ul>
</body>
</html>

当然你也可以利用:first-child伪类和:last-child伪类(当然这种效果IE6完全不支持,IE7,IE8部分支持,其中IE7和IE8效果相同,不支持:last-child),比如:

http://jsfiddle.net/kingterrors/44GzJ/embedded/result,html,css/

PS:由于近日(2014年6月)jsfiddle无法正常访问,可能受内网影响,现将之前所有jsfiddle预览去除,不过你仍然可将以上地址拷贝到浏览器预览,或选择尝试以下代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>how to remove margins for first last elements</title>
<style type="text/css">
ul {
    border: 1px solid #000;
    margin: 0;
    padding: 0;
    list-style: none;
    float:left;
}
ul li {
    background:#eee;
    color: #F00;
    margin: 50px;
}
ul li:first-child {
    color: #000;
    margin-top: 0 !important;
    margin-left: 0 !important;
}
ul li:last-child {
    color: #0f0;
    margin-bottom: 0 !important;
    margin-right: 0 !important;
}
</style>
</head>
<body>
<ul>
  <li>Hello, This is first element</li>
  <li>Whidy! so many elements</li>
  <li>Whidy! so many elements</li>
  <li>Whidy! so many elements</li>
  <li>Here it is, The last element</li>
</ul>
</body>
</html>
IE6,IE7,IE8都不能完好支持first-child和last-child伪类

其中还有种很另类的方式,给任意元素的规则性的添加伪类.比如你有5个li元素,你想让每两个li有区别,比如应用在有些特殊列表,你给每两行加上不同的背景色,我这里随便做了个效果给大家参考:

http://jsfiddle.net/kingterrors/76jxP/embedded/result,html,css/

PS:由于近日(2014年6月)jsfiddle无法正常访问,可能受内网影响,现将之前所有jsfiddle预览去除,不过你仍然可将以上地址拷贝到浏览器预览,或选择尝试以下代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>how to remove margins for first last elements</title>
<style type="text/css">
ul {
    border: 1px solid #000;
    margin: 0;
    padding: 0;
    list-style: none;
    float:left;
}
ul li {
    background:#eee;
    color: #F00;
    margin: 50px;
}
ul li:nth-child(2n) {
    color: #000;
    margin-top: 0 !important;
    margin-left: 0 !important;
}
</style>
</head>
<body>
<ul>
  <li>Hello, This is first element</li>
  <li>Whidy! so many elements</li>
  <li>Whidy! so many elements</li>
  <li>Whidy! so many elements</li>
  <li>Here it is, The last element</li>
</ul>
</body>
</html>

当然这个在IE8以下包括IE8的版本都是不被支持的 😯 !

最后总结一下:first-child和:last-child伪类在IE6下是完全不支持的,而IE7和IE8仅支持:first-child,IE9是完全支持的.而:nth-child只有IE9支持,其他的比如Safari 3+, Firefox 3.5+ and Chrome 1+是完全支持以上效果的.

另外,你也可以用jq来控制某个任意元素的样式,之前我也提到过,有兴趣可以看看列表中最后一个元素样式清除修改方法 🙄

如果有兴趣可以参考下原文,Remove Margins for First/Last Elements

有趣的透视屏幕图~

今天在看smashingMagazine的时候看到一篇十分有趣的文章Beautiful Examples of Transparent Screen Trick Photos,大致内容是这样的:

“我们找到了一些独特的而且有创意的东西来提升你的精神和挑战你的创造力,一旦将这些显眼的,有吸引力的幻想应用到电脑屏幕上,结果会变得十分有趣和幻觉一般…那么就拍一张”透明的”显示器图片吧.这个创意十分简单:你拍一张周围环境的图片,将它处理一下后设置为显示器桌面壁纸,当你的角度恰好的时候,你将发现神奇一般的效果,显示器好像是透视了一样,既然如此简单我们又能通过它做点什么神奇的事情呢?”

接下来我将展示几张它们做的十分神奇的图片

很显然其中有一张比较粗糙的图是我做的,HOHO,,,纯属娱乐了,,,觉得还是很有意思的,嗯嗯,有兴趣的朋友也可以试一下更加奇妙的效果,,,睡觉咯~

部分内容转载自:http://www.smashingmagazine.com/2010/08/07/beautiful-examples-of-transparent-screen-trick-photos/

WordPress 3.1 Beta 1 发布

前天,wordpress官方网站新闻更新了说wp 3.1beta1版本发布了,比较激动,去看了看,,,以下是我简单的原文翻译:

又到了一个开发周期的发布时刻了,此时所有基本功能已经完成,也消除了很多BUG.请喜欢追新的朋友尝试一下这个新版本吧!当然,现在这个版本还在开发阶段,我们不建议你将它作为目前正在使用的网站上,最好是仅仅用来测试,当然如果你发现了问题,及时通知我们,当然如果有可能的话,未尝不可帮我们解决这个问题,我们将很高兴!

如果一切都很顺利的话,wordpress 3.1将于年底发布,当然实际情况将取决于这个测试版的测试结果了,你帮我们查到的问题越快越多,我们也将更快的推出稳定的版本.

如果你想成为测试人员,你需要了解有关报告错误的知识(<<如何提交错误(原文:how to report bugs)>>)一下将介绍这次更新带来的变化:

  1. 发布文章的格式(详见:#14746)
  2. 主题搜索 (详见:#14936)
  3. 内部链接 (详见:#11420)
  4. 管理工具条(详见:#14772)
  5. 交互式管理(详见:#14579)
  6. 更新TinyMCE(即编辑器,详见:#12574)
  7. 多分类查询(详见:#12891)
  8. 自定义文章索引页(详见:#13818)
  9. CSS清除管理(详见:#14770)
  10. 用户管理(详见:#14696)
  11. 网络管理(详见:#14435)
  12. 更新密码重置方式(Password Reset Redux,详见:#5919)

当然,还有一些待验证的问题,还没有完全的完成,在这个测试版中没有提到.它会将在3.1普及使用之前解决的….(后面一大串,我就不详述了,大致的更新内容简单介绍到这里,也希望,WP能更好的完善部分功能,其实我还是比较期待内置编辑器的变化~)

时间不早了,睡觉了~

测试版本下载地址:Download WordPress 3.1 Beta 1

原文来自:http://wordpress.org/news/2010/11/wordpress-3-1-beta-1/

通过photoshop的阴影/高光工具调整相片曝光问题(下)

上次翻译了一半<<通过photoshop的阴影/高光工具调整相片曝光问题(上)>>.近期比较忙,今天抽点时间继续写完,以了心事

高光

调节阴影的部分和高光的作用相同,只不过是减少高光替换成了减少阴影,即使你觉得必须对高光部分进行修改,也不要紧:你所有做的事情对这个整体的对比都会产生很大的影响.其实我觉得我很少用到高光部分.来看看究竟什么是对你有效的.

调整

首先,我们来看这最后两个滑动块:颜色校正中间调对比度.实际上颜色校正滑块应该叫做饱和度滑块,当它单独滑动时来提高或降低饱和度的.在阴影高光调整之前,我用它来重新调整其饱和度让它看起来很合适.当然比起这里的饱和度调整,我更加偏向于使用调整图层来使修改变得更加简单.

中间调对比度滑块可以被用来提高或降低中间色调的对比度.完美而又简单:就是名副其实.然后我继续重复刚才的操作.这次将对比度还原,保持原始的效果.

在上面这张图中,通过阴影部分的调整,我又重新调整了颜色校正中间调对比度这样使树叶(也就是图上的圈圈部分)看起来更加真实.(这里并没有调整高光区域).在修正了阴影和高光后,我可以通过色相/饱和度或者是添加其他调整图层来实现不同的效果.

实例

OK,拖了若干天,总算完成了,心得也不想写了,不过学的知识是活用的,希望大家在了解了这个工具的同时,能够更好的运用到平时的设计中~

原文出处: Correcting Exposure with the Shadows & Highlights Tool

通过photoshop的阴影/高光工具调整相片曝光问题(上)

这篇文章通过photoshop的”阴影/高光”工具调整相片曝光来展现出相片的最美一面!

引言

复制图层

今天我们来共同了解下这个极其有用的,不可思议的工具:阴影/高光调整工具

当我们在拍照的时候,很难或者说几乎不可能在每次拍出来的照片中获得最佳的曝光度. 尤其是在户外,拍摄高反差的景物时,经常会把要拍的东西拍得曝光过度或者曝光不足.那么,阴影/高光调整工具将会充分发掘你所拍的照片的最大潜力.
那么接下来就让我们一起看看吧!

阴影/高光介绍

工具面板

首先,它并不算是一个调整图层一样的东西,所以你可以通过Ctrl+J(Win)或Command+J(Mac)先复制图层,这样你就可以直接修改这个图,当然感觉不好的话也可以还原,因为你有原始图层.

复制完图层后,接下来我们开始进入正题!

其次,Image>Adjustments>Shadows/Highlights…(图像>调整>阴影/高光 *因为我也是用的英文版PS CS5,不知道中文版是不是这样的,若不是请及时通知我~)打开阴影/高光,在这个面板的底部,找到Show More Options(查看更多选项)的选择框,并勾上,这样这些对于新手看似复杂的更多的调整项目就展现出来了,接下来我们一个个看,相信我,你将十分感谢居然有如此强大的控制功能.

最后这一步,你可做可不做,这不过是我的个人习惯罢了.这里的所有值都是photoshop默认的.当你在处理不同的图片时这些值对你来说毫无用处.当然我更加偏向于在处理图片之前将Shadows(阴影) 和 Highlights(高光)框框里面的Amount(数量)Tonal Width(色调宽度), 和 Radius(半径) 设置为0 (也就是全部调整至最左边). 把在Adjustments(调整)框内的Color Correction(颜色校正)Midtone Contrast(中间调对比度) 设置为0 (也就是滑动条的中央). 最后点击 Save as Defaults(存储为默认值)这个按钮. 那么以后每当你打开Shadows/Highlights(阴影/高光)时它永远都不会改变了.

数量,色调宽度和半径

你可以在阴影框和高光框内看到这三个滑动条,我们先来看看阴影框.

数量

数量

我是这样理解的,它会根据你的调整对图像进行较大的改变(当然即使不勾上Show More Options(查看更多选项)依然能够直接调),这里你可以分别将阴影部分调亮或者高亮部分调暗.这个好像可以两边滑动的小刷子,我想你也许用过,也知道它的作用,当然我重点要说的是下面两个滑块的作用.

色调宽度

色调宽度

这里我们来看看怎么样的一个范围可以影响图片.滑块调整到0%,意味着只有阴影部分最黑的地方会被改变,通过向右拖动滑块,慢慢的会影响到中间色调.

半径

半径

半径滑块决定了你想调整的区域在图片该处的其他多大的范围将会被渲染.当然你必须输入一个大于0的值,否则图片看起来灰又像被洗过的.这样你就会知道它对图片的影响效果有么多好了,在3-15px这个值之间,不多也不少,看起来图片变得清爽而干净.我十分喜欢这个感觉,在20px或更高的时候效果变得使图片的区别更加大,不是感到混到一起了就是感觉模糊了.那么设置的越高,就越混…(*其实我对原文理解不够,我尝试着在图片上修改,真的没感觉到什么变化,其实我也不是很会用这个囧rz)

笔记

其实你可以看出来,正如我所说,你无法将每个调整至完美,我经常使用的方法是将数量调到35%左右,色调宽度则必须提高(*作者没有说调至多少.那估计看效果行事了~)最后将半径调整至5px,最后根据当前状态进行细微调整.

哎呀,第一次翻译外国的文章才发现原来这么辛苦,自己经常看国外的好东西,感觉好像理解起来很简单,但是对不懂E问的童鞋来说,估计看了我的也算是很杯具.除此翻译多多包涵.(话说搞了三个小时,头都大了,除了翻译,版式总是调不好…休息下,今天到此为止吧~)

原文出处: Correcting Exposure with the Shadows & Highlights Tool