Skip to content

页面样式与布局 ​

qinjs 的 vue 页面是 webview 渲染的

qinjs 的 css 与 web 的 css 基本一致。本文没有讲解 css 的用法。在你了解 web 的 css 的基础之上,本文讲述一些样式相关的注意事项。

本文重点介绍 vue 页面,也就是webview中的样式注意事项。

css预处理器支持 ​

qinjs 支持less、sass、scss、stylus等预处理器。

参考: css预处理器

尺寸单位 ​

qinjs 支持的通用 css 单位包括 px、rpx

  • px 即屏幕像素
  • rpx 即响应式 px,一种根据屏幕宽度自适应的动态单位。以 750 宽的屏幕为基准,750rpx 恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大,但在 App(vue2 不含 nvue) 端和 H5(vue2) 端屏幕宽度达到 960px 时,默认将按照 375px 的屏幕宽度进行计算,具体配置参考:rpx 计算配置 。

vue 页面支持下面这些普通 H5 单位,但在 nvue 里不支持:

  • rem 根字体大小可以通过 page-meta 配置抖音小程序和飞书小程序:屏幕宽度/20、百度小程序:16px、支付宝小程序:50px
  • vh viewpoint height,视窗高度,1vh 等于视窗高度的 1%
  • vw viewpoint width,视窗宽度,1vw 等于视窗宽度的 1%

下面对 rpx 详细说明:

设计师在提供设计图时,一般只提供一个分辨率的图。

严格按设计图标注的 px 做开发,在不同宽度的手机上界面很容易变形。

而且主要是宽度变形。高度一般因为有滚动条,不容易出问题。由此,引发了较强的动态宽度单位需求。

微信小程序设计了 rpx 解决这个问题。qinjs 在 H5 端都支持了 rpx,并且可以配置不同屏幕宽度的计算方式,具体参考:rpx 计算配置。

rpx 是相对于基准宽度的单位,可以根据屏幕宽度进行自适应。qinjs 规定屏幕基准宽度 750rpx。

开发者可以通过设计稿基准宽度计算页面元素 rpx 值,设计稿 1px 与框架样式 1rpx 转换公式如下:

设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx

换言之,页面元素宽度在 qinjs 中的宽度计算公式:

750 * 元素在设计稿中的宽度 / 设计稿基准宽度

举例说明:

  1. 若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 qinjs 里面的宽度应该设为:750 * 100 / 750,结果为:100rpx。
  2. 若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 qinjs 里面的宽度应该设为:750 * 100 / 640,结果为:117rpx。
  3. 若设计稿宽度为 375px,元素 B 在设计稿上的宽度为 200px,那么元素 B 在 qinjs 里面的宽度应该设为: 750 * 200 / 375,结果为:400rpx。

Tips

  • 注意 rpx 是和宽度相关的单位,屏幕越宽,该值实际像素越大。如不想根据屏幕宽度缩放,则应该使用 px 单位。
  • 如果开发者在字体或高度中也使用了 rpx ,那么需注意这样的写法意味着随着屏幕变宽,字体会变大、高度会变大。如果你需要固定高度,则应该使用 px 。
  • rpx 不支持动态横竖屏切换计算,使用 rpx 建议锁定屏幕方向
  • 设计师可以用 iPhone6 作为视觉稿的标准。

样式导入 ​

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

示例代码:

html
<style>
    @import "../../common/qin.css";

    .qin-card {
        box-shadow: none;
    }
</style>
<style>
    @import "../../common/qin.css";

    .qin-card {
        box-shadow: none;
    }
</style>

内联样式 ​

框架组件上支持使用 style、class 属性来控制组件的样式。

  • style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
html
<view :style="{color:color}" />
<view :style="{color:color}" />
  • class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
html
<view class="normal_view" />
<view class="normal_view" />

选择器 ​

目前支持的选择器有:

选择器样例样例描述
.class.intro选择所有拥有 class="intro" 的组件
#id#firstname选择拥有 id="firstname" 的组件
elementview选择所有 view 组件
element, elementview, checkbox选择所有文档的 view 组件和所有的 checkbox 组件
::afterview::after在 view 组件后边插入内容,仅 vue 页面生效
::beforeview::before在 view 组件前边插入内容,仅 vue 页面生效

注意:

  • 在 qinjs 中不能使用 * 选择器。

  • 微信小程序自定义组件中仅支持 class 选择器

  • page 相当于 body 节点,例如:

    css
    <!-- 设置页面背景颜色,使用 scoped 会导致失效 -- > 
    page {
      background-color: #ccc;
    }
    <!-- 设置页面背景颜色,使用 scoped 会导致失效 -- > 
    page {
      background-color: #ccc;
    }

全局样式与局部样式 ​

定义在 App.vue 中的样式为全局样式,作用于每一个页面。在 pages 目录下 的 vue 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 App.vue 中相同的选择器。

注意:

  • App.vue 中通过 @import 语句可以导入外联样式,一样作用于每一个页面。

CSS 变量 ​

qinjs 提供内置 CSS 变量

CSS 变量描述App小程序H5
--status-bar-height系统状态栏高度系统状态栏高度、nvue 注意见下25px0
--window-top内容区域距离顶部的距离00NavigationBar 的高度
--window-bottom内容区域距离底部的距离00TabBar 的高度

注意:

  • var(--status-bar-height) 此变量在微信小程序环境为固定 25px,在 App 里为手机实际状态栏高度。
  • 当设置 "navigationStyle":"custom" 取消原生导航栏后,由于窗体为沉浸式,占据了状态栏位置。此时可以使用一个高度为 var(--status-bar-height) 的 view 放在页面顶部,避免页面内容出现在状态栏。
  • 由于在 H5 端,不存在原生导航栏和 tabbar,也是前端 div 模拟。如果设置了一个固定位置的居底 view,在小程序和 App 端是在 tabbar 上方,但在 H5 端会与 tabbar 重叠。此时可使用--window-bottom,不管在哪个端,都是固定在 tabbar 上方。

代码块

快速书写 css 变量的方法是:在 css 中敲 hei,在候选助手中即可看到 3 个 css 变量。(HBuilderX 1.9.6 以上支持)

示例 1 - 普通页面使用 css 变量:

html
<template>
  <page-meta>
    <navigation-bar />
  </page-meta>
  <view>
    <view class="status_bar">
      <!-- 这里是状态栏 -->
    </view>
    <view>状态栏下的文字</view>
  </view>
</template>
<style>
  .status_bar {
    height: var(--status-bar-height);
    width: 100%;
  }
</style>
<template>
  <page-meta>
    <navigation-bar />
  </page-meta>
  <view>
    <view class="status_bar">
      <!-- 这里是状态栏 -->
    </view>
    <view>状态栏下的文字</view>
  </view>
</template>
<style>
  .status_bar {
    height: var(--status-bar-height);
    width: 100%;
  }
</style>
html
<template>
  <view>
    <view class="toTop">
      <!-- 这里可以放一个向上箭头,它距离底部tabbar上浮10px-->
    </view>
  </view>
</template>
<style>
  .toTop {
    bottom: calc(var(--window-bottom) + 10px);
  }
</style>
<template>
  <view>
    <view class="toTop">
      <!-- 这里可以放一个向上箭头,它距离底部tabbar上浮10px-->
    </view>
  </view>
</template>
<style>
  .toTop {
    bottom: calc(var(--window-bottom) + 10px);
  }
</style>

示例 2 - vue 页面获取状态栏高度

html
<template>
  <view class="content">
    <view :style="{ height: iStatusBarHeight + 'px'}"></view>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        iStatusBarHeight: 0,
      };
    },
    onLoad() {
      this.iStatusBarHeight = qin.getSystemInfoSync().statusBarHeight;
    },
  };
</script>
<template>
  <view class="content">
    <view :style="{ height: iStatusBarHeight + 'px'}"></view>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        iStatusBarHeight: 0,
      };
    },
    onLoad() {
      this.iStatusBarHeight = qin.getSystemInfoSync().statusBarHeight;
    },
  };
</script>

固定值 ​

qinjs 中以下组件的高度是固定的,不可修改:

组件描述AppH5
NavigationBar导航栏44px44px
TabBar底部选项卡HBuilderX 2.3.4 之前为 56px,2.3.4 起和 H5 调为一致,统一为 50px。(但可以自主更改高度)50px

各小程序平台,包括同小程序平台的 iOS 和 Android 的高度也不一样。

Flex 布局 ​

为支持跨平台,框架建议使用 Flex 布局,关于 Flex 布局可以参考外部文档A Complete Guide to Flexbox、阮一峰的 flex 教程等。

背景图片 ​

qinjs 支持使用在 css 里设置背景图片,使用方式与普通 web 项目大体相同,但需要注意以下几点:

  • 支持 base64 格式图片。
  • 支持网络路径图片。
  • 小程序不支持在 css 中使用本地文件,包括本地的背景图和字体文件。需以 base64 方式方可使用。
  • 使用本地路径背景图片需注意:
    1. 为方便开发者,在背景图片小于 40kb 时,qinjs 编译到不支持本地背景图的平台时,会自动将其转化为 base64 格式;
    2. 图片大于等于 40kb,会有性能问题,不建议使用太大的背景图,如开发者必须使用,则需自己将其转换为 base64 格式使用,或将其挪到服务器上,从网络地址引用。
    3. 本地背景图片的引用路径推荐使用以 ~@ 开头的绝对路径。
    css
    .test2 {
      background-image: url('~@/static/logo.png');
    }
    .test2 {
      background-image: url('~@/static/logo.png');
    }

注意

  • 微信小程序不支持相对路径(真机不支持,开发工具支持)

字体图标 ​

qinjs 支持使用字体图标,使用方式与普通 web 项目相同,需要注意以下几点:

  • 支持 base64 格式字体图标。
  • 支持网络路径字体图标。
  • 小程序不支持在 css 中使用本地文件,包括本地的背景图和字体文件。需以 base64 方式方可使用。
  • 网络路径必须加协议头 https。
  • 从 http://www.iconfont.cn 上拷贝的代码,默认是没加协议头的。
  • 从 http://www.iconfont.cn 上下载的字体文件,都是同名字体(字体名都叫 iconfont,安装字体文件时可以看到),在 nvue 内使用时需要注意,此字体名重复可能会显示不正常,可以使用工具修改。
  • 使用本地路径图标字体需注意:
    1. 为方便开发者,在字体文件小于 40kb 时,qinjs 会自动将其转化为 base64 格式;
    2. 字体文件大于等于 40kb,仍转换为 base64 方式使用的话可能有性能问题,如开发者必须使用,则需自己将其转换为 base64 格式使用,或将其挪到服务器上,从网络地址引用;
    3. 字体文件的引用路径推荐使用以 ~@ 开头的绝对路径。
    css
    @font-face {
      font-family: test1-icon;
      src: url('~@/static/iconfont.ttf');
    }
    @font-face {
      font-family: test1-icon;
      src: url('~@/static/iconfont.ttf');
    }

nvue中不可直接使用 css 的方式引入字体文件,需要使用以下方式在 js 内引入。nvue 内不支持本地路径引入字体,请使用网络链接或者base64形式。src字段的url的括号内一定要使用单引号。

js
var domModule = weex.requireModule('dom');
domModule.addRule('fontFace', {
  fontFamily: 'fontFamilyName',
  src: "url('https://...')",
});
var domModule = weex.requireModule('dom');
domModule.addRule('fontFace', {
  fontFamily: 'fontFamilyName',
  src: "url('https://...')",
});

示例:

html
<template>
  <view>
    <view>
      <text class="test">&#xe600;</text>
      <text class="test">&#xe687;</text>
      <text class="test">&#xe60b;</text>
    </view>
  </view>
</template>
<style>
  @font-face {
    font-family: 'iconfont';
    src: url('https://at.alicdn.com/t/font_865816_17gjspmmrkti.ttf') format('truetype');
  }
  .test {
    font-family: iconfont;
    margin-left: 20rpx;
  }
</style>
<template>
  <view>
    <view>
      <text class="test">&#xe600;</text>
      <text class="test">&#xe687;</text>
      <text class="test">&#xe60b;</text>
    </view>
  </view>
</template>
<style>
  @font-face {
    font-family: 'iconfont';
    src: url('https://at.alicdn.com/t/font_865816_17gjspmmrkti.ttf') format('truetype');
  }
  .test {
    font-family: iconfont;
    margin-left: 20rpx;
  }
</style>