单项目里的多终端自适应

53 阅读2分钟

背景

网站需要适配移动端,但是不能切换域名,只能在一个项目里适配,然后设计的移动端页面结构与PC端存在相当的差异,单纯通过CSS进行适配,过于麻烦且难以实现。

代码

  1. CSS使用vw、rem、sass/less实现等比例还原UI设计(类似小程序的rpx方案):

使页面结构在一定区间的分辨率内缩放与UI设计稿尽量一致。

// variables-desktop.scss

// 1440px为UI设计稿宽度
// 12px = 100vw / 1440px * 12;
$root-font-size: 0.83vw;

@function fs($font-size) {
  @return calc($font-size / 12) + rem;
}
// variables-mobile.scss

// 750px为UI设计稿宽度
// 12px = 100vw / 750px * 12;
$root-font-size: 1.6vw;
@function fs($font-size) {
  @return calc($font-size / 12) + rem;
}
// public.scss

@import './variables-desktop.scss';

html {
  font-size: $root-font-size;
}
@import './mobile.scss';
// mobile.scss

@import './variables-mobile.scss';

@media (max-width: 750px) {
    html {
      font-size: $root-font-size;
    }
}
// pages/Page/Desktop/index.module.scss

@import './variables-desktop.scss';
.box {
    // width: 1440px;
    width: fs(1440);
}

rpx2rem

// variables-mobile.scss

// 750px为UI设计稿宽度
// 12px = 100vw / 750px * 12;
$root-font-size: 1.6vw;
@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str- slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}
@function fs($font-size) {
    $a: calc($font-size / 12) + '';
    $b: str-replace($a,'rpx','');
    $c: unquote($b);

  @return $c + rem;
}
  1. 在复杂组件内使用JS判断

在PC/Mobile设计稿的结构差异过大的情况下使用,如页面组件 这里的例子是借用了ahooks的 useResponsive 封装了一个Context:

//context/ResponsiveProvider/useResponsive.ts

import { useEffect, useMemo, useState } from 'react';
import { configResponsive, useResponsive as useResponsiveBase } from 'ahooks';

configResponsive({
  mobile: 0,
  tablet: 751,
  desktop: 1281,
});

export default function useResponsive() {
  const responsive = useResponsiveBase();
  const [device, setDevice] = useState('desktop');

  useEffect(() => {
    if (responsive?.desktop) {
      setDevice('desktop');
    } else if (responsive?.tablet) {
      setDevice('tablet');
    } else if (responsive?.mobile) {
      setDevice('mobile');
    }
  }, [responsive]);

  return useMemo(() => ({ device } as const), [device]);
}
// pages/Page/index.tsx

import React from 'react';

import { useResponsiveContext } from '@/context/ResponsiveProvider';
import type { Props } from './interface';
import Desktop from './Desktop';
import Mobile from './Mobile';

const Page = (props: Props) => {
  const { device } = useResponsiveContext();

  if (device === 'mobile') {
    return <Mobile {...props} />;
  }
  return <Desktop {...props} />;
};

export type { Props };
export default Page;
  1. 在简单组件内使用CSS判断:

在PC/Mobile设计稿的结构类似的情况下使用,如Button组件

// public.scss

@import '@/styles/variables-desktop.scss';

.btn {
  font-size: 14px;
}
@import './mobile.scss';
// mobile.scss

@import '@/styles/variables-mobile.scss';

@media (max-width: 750px) {
  .btn {
    font-size: 12px;
  }
}