Caso de maquetación CSS: no habrá nadie que no pueda maquetar

El diseño CSS es la lección más importante sobre el front-end. Si aprende el diseño CSS, puede comenzar. Este artículo resume casos de diseño comunes, que se pueden usar como materiales de aprendizaje para el diseño de CSS y también se pueden usar como materiales de referencia para el desarrollo. Se recomienda que lo marque primero. Si le resulta útil, puede considerar darle un pequeño elogio.

centrar horizontalmente

Requisitos de diseño centrados horizontalmente: suponga que el ancho del contenedor es xxx , el ancho del contenido medio esyyy , luego ancho del margen izquierdo = ancho del margen derecho =( x − y ) / 2 (xy)/2( Xy ) /2 , como se muestra en la siguiente figura:

inserte la descripción de la imagen aquí

Método 1, margen: automático;

    <style>
      .box {
      
      
        height: 50vh;
        background-color: #fdeff2;
      }

      .content {
      
      
        width: 150px;
        height: 100px;
        background-color: #f6bfbc;

        margin: 0 auto; /*居中*/
      }
    </style>

    <div class="box">
      <div class="content"></div>
    </div>

[Interpretación de los puntos clave] El significado del centrado horizontal: "Centrado" solo tiene sentido cuando el ancho del contenedor es mayor que el contenido, por lo que la premisa de usar este método es que el ancho del contenido es menor que el ancho de El contenedor.

[Punto propenso a errores] Se utiliza para contenido que es igual al ancho del contenedor margin:auto;. Por ejemplo, cuando el contenedor es una caja flotante, el contenedor de posicionamiento fuera de flujo.

[Principio] El valor automático del margen es igual al ancho del espacio restante, y el margin-left: auto;contenido se empujará hacia la derecha. Si la izquierda y la derecha se configuran al mismo tiempo, margin: 0 auto;la izquierda y la derecha dividirán el espacio restante por igual. .

[Consejos] margin: 0 auto;Se puede abreviar como: margin: auto;porque cuando margin-top o margin-bottom es automático, el valor es 0, a menos que esté fuera del flujo del documento.

Método 2. Caja flexible

    <style>
      .box {
      
      
        height: 150px;
        background-color: #fdeff2;
        display: flex;
        justify-content: center; /*居中*/
      }

      .content {
      
      
        width: 150px;
        height: 100px;
        background-color: #f6bfbc;
      }
    </style>

    <div class="box">
      <div class="content"></div>
    </div>

[Interpretación] La caja elástica tiene un esquema de centrado especial: es decir, establece el centro en la dirección del eje principal y el eje transversal.

Método 3, alineación de texto: centro

Cuando el contenido es un elemento sin nivel de bloque, el efecto de centrado se text-align:center;puede :

    <style>
      ul {
      
      
        text-align: center;

        /* 其他样式 */
        line-height: 40px;
        list-style: none;
        margin: 0;
        padding: 0;
        background-color: #fdeff2;
      }

      ul li {
      
      
        display: inline-block;

        /* 其他样式 */
        background-color: #f6bfbc;
        padding: 8px 16px;
      }
    </style>
    <ul>
      <li>首页</li>
      <li>关于</li>
      <li>产品</li>
    </ul>

inserte la descripción de la imagen aquí

[Interpretación de puntos clave] El método de alineación de texto se usa a menudo cuando el texto está centrado, y este atributo se hereda, lo cual es muy conveniente de usar. Cuando se usa para el diseño, los enlaces en la barra de navegación de idioma común se centran, lise configuran inline-blocky luego se centran.

[Errores] No distinguió entre el contenedor y el contenido, y configuró el bloque en línea en el elemento del contenedor.

[Punto propenso a errores] Se utiliza para contenedores con el mismo ancho y contenido, como contenedores flotantes.

Método 4. Realización de posicionamiento

    <style>
      .box {
      
      
        height: 200px;
        background-color: #fdeff2;

        position: relative;
      }

      .content {
      
      
        width: 150px;
        height: 100px;
        background-color: #f6bfbc;

        /* 定位实现水平居中
        1. left=right
        2. 剩余空间的宽度大于零
        3. 内容宽度已知
        */
        position: absolute;
        left: 0;
        right: 0;
        margin: auto;
      }
    </style>

    <div class="box">
      <div class="content"></div>
    </div>

[Interpretación de puntos clave] Establezca las distancias izquierda y derecha para que sean iguales, y luego establezcamargin: auto;

[Punto propenso a errores] Necesita saber el ancho del contenido. Si no establece el ancho del contenido, el contenedor se llenará.

resumen

¿Has aprendido tantos métodos de centrado horizontal?

[Ejercicio] Nombre varios métodos de centrado horizontal y cuáles son sus ventajas y desventajas.

centro vertical

Método 1. La altura de línea realiza el centrado vertical del texto

Idea: establezca la altura de la línea a la altura del contenedor para centrar el texto.

<style>
  .box {
      
      
    height: 50px;
    background-color: #fdeff2;
  }

  .content {
      
      
    line-height: 50px;
    background-color: #f6bfbc;
    color: #b94047;
  }
</style>

<div class="box">
  <div class="content">你猜我居中了没</div>
</div>

inserte la descripción de la imagen aquí

Método 2: alineación vertical para centrar la imagen y el texto

    <style>
      .box {
      
      
        line-height: 50px;
        background-color: #fdeff2;
        color: #b94047;
      }

      .box img {
      
      
        height: 30px;
        vertical-align: middle;
      }

      .box span {
      
      
        vertical-align: middle;
      }
    </style>

    <div class="box">
      <img src="https://s1.52poke.wiki/wiki/thumb/5/53/054Psyduck.png/300px-054Psyduck.png" alt="图不见了" />
      <span>这可怎么居中呀</span>
    </div>

inserte la descripción de la imagen aquí

[Puntos] Este método solo se puede usar para elementos con propiedades en línea, y la altura del contenido es line-heightmenos efectiva.

Método 3. Caja flexible

Flexbox se puede centrar verticalmente fácilmente:

    <style>
      .box {
      
      
        height: 50px;
        display: flex;
        align-items: center;

        background-color: #fdeff2;
        color: #b94047;
      }

      .box img {
      
      
        height: 30px;
      }
    </style>

    <div class="box">
      <img src="https://s1.52poke.wiki/wiki/thumb/5/53/054Psyduck.png/300px-054Psyduck.png" alt="图不见了" />
      <span>这可怎么居中鸭</span>
    </div>

inserte la descripción de la imagen aquí

[Interpretación de los puntos clave] Úselo align-items:center;para lograr un centrado vertical y utilícelo justify-content:center;para lograr un centrado horizontal. Una declaración más precisa es: align-items:center;realice el centrado de la dirección del eje transversal, justify-content:center;realice el centrado de la dirección del eje principal, la dirección del eje principal se flex-directiondeclara y el valor predeterminado es de izquierda a derecha.

[Punto propenso a errores] El centrado vertical solo se puede lograr cuando la altura del contenedor es mayor que el contenido.

Método 4. Posicionamiento para lograr el centrado vertical

    <style>
      .box {
      
      
        height: 100px;
        background-color: #fdeff2;

        position: relative;
      }

      .content {
      
      
        width: 20px;
        height: 50px;
        background-color: #f6bfbc;

        /* 定位实现垂直居中
        1. top=bottom, 设置 margin: auto;
        2. 剩余空间的高度大于零
        3. 内容高度已知
        */
        position: absolute;
        right: 20px;
        top: 0;
        bottom: 0;
        margin: auto;
      }
    </style>

    <div class="box">
      <div class="content"></div>
    </div>

inserte la descripción de la imagen aquí

[Interpretación de los puntos clave] Establezca las distancias superior e inferior para que sean iguales, y luego configure margin: auto;para lograr esto. Este método se usa principalmente para el diseño de la barra de herramientas a la derecha.

Existe otro método de posicionamiento, el método de traducción:

    <style>
      .box {
      
      
        height: 100px;
        background-color: #fdeff2;

        position: relative;
      }

      .content {
      
      
        width: 20px;
        height: 50px;
        background-color: #f6bfbc;

        /* 定位实现垂直居中
        1. 先让上边界居中,然后用平移调整
        2. 剩余空间的高度大于零
        3. 内容高度已知
        */
        position: absolute;
        right: 20px;
        top: 50%;
        transform: translateY(-50%);
      }
    </style>

    <div class="box">
      <div class="content"></div>
    </div>

resumen

El centrado vertical es un método común para el diseño de páginas web. El centrado vertical es un poco más problemático que el centrado horizontal. Pero con flexbox, todo se vuelve más fácil.Después de todo, flexbox está diseñado para el diseño.

【Ejercicio】Dígame varios métodos de centrado vertical y cuáles son las ventajas y desventajas de cada uno.

diseño de dos columnas

Como se muestra en la figura a continuación, el diseño de dos columnas requiere:

1) Ancho izquierdo fijo

2) El lado derecho ocupa el ancho restante

3) El lado izquierdo no se desplaza con el contenido del lado derecho

inserte la descripción de la imagen aquí

Un diseño de dos columnas se usa comúnmente en los sistemas de administración en segundo plano, con un menú de navegación de varios niveles a la izquierda y detalles del sistema a la derecha. También se usa comúnmente en sistemas de documentos, con directorios de varios niveles a la izquierda y contenido de documentos a la derecha.

Método 1. Utilice el posicionamiento para lograr un diseño de dos columnas

    <style>
      body {
      
      
        margin: 0;
      }

      .home-side {
      
      
        /* 实现固定侧边栏 
         * 必须同时设置 top 和 bottom
        */
        position: fixed;
        top: 0;
        bottom: 0;

        /* 设置侧边栏宽度 */
        width: 200px;

        /* 设置内容溢出滚动效果 */
        overflow-y: auto;
      }

      .side-content {
      
      
        width: 100%;
        height: 120vh;
        background-color: #e9dfe5;
      }

      .home-main {
      
      
        /* 使用左外边距留出侧边栏宽度 */
        margin-left: 200px;

        background-color: #f5b1aa;
        height: 200vh;
      }
    </style>
    <div class="home">
      <aside class="home-side">
        <div class="side-content"></div>
      </aside>
      <main class="home-main"></main>
    </div>

【Puntos clave】

1) Use el posicionamiento fijo para hacer que la barra lateral quede fija en el lado izquierdo. Para hacer que la barra lateral se pueda desplazar, también debe configurar las propiedades superior, inferior y de desbordamiento al mismo tiempo.

2) Use margin o padding para dejar el contenido de la barra lateral para el contenido.

Darse cuenta del efecto:

inserte la descripción de la imagen aquí

Si se abandona la tercera condición: es decir, la barra lateral puede desplazarse con el contenido, habrá muchos métodos de diseño:

Método 2, diseño flexible

    <style>
      body {
      
      
        margin: 0;
      }

      .home {
      
      
        display: flex;
      }

      .home-side {
      
      
        width: 200px;
        flex-shrink: 0; /*不允许收缩*/
      }

      .home-main {
      
      
        flex-grow: 1; /*占据剩余空间*/

        background-color: #f5b1aa;
        height: 200vh;
      }

      .side-content {
      
      
        width: 100%;
        height: 120vh;
        background-color: #e9dfe5;
      }
    </style>

    <div class="home">
      <aside class="home-side">
        <div class="side-content"></div>
      </aside>
      <main class="home-main"></main>
    </div>

[Interpretación de los puntos principales] El código clave tiene solo cuatro líneas:

      .home {
    
    
        display: flex;
      }

      .home-side {
    
    
        width: 200px;
        flex-shrink: 0; /*不允许收缩*/
      }

      .home-main {
    
    
        flex-grow: 1; /*占据剩余空间*/
	  }

[Ventajas] Simple y fácil de entender.

[Desventaja] La barra lateral no se puede arreglar.

【Habilidades】flex:1;Equivalente aflex-grow:1;

Diseño de barra lateral con ancho redimensionable

No se puede lograr una barra lateral fija con ancho variable sin JavaScript. Aquí hay un caso solo como referencia:

    <style>
      body {
      
      
        margin: 0;
      }
      
      :root {
      
      
        --sidebar-width: 200px;
      }

      .home-side {
      
      
        /* 实现固定侧边栏 
         * 必须同时设置 top 和 bottom
        */
        position: fixed;
        top: 0;
        bottom: 0;

        box-sizing: border-box;
        /* 设置侧边栏宽度 */
        width: var(--sidebar-width);
      }

      .side-resizer {
      
      
        position: absolute;
        right: 0;
        top: 0;
        bottom: 0;

        cursor: ew-resize;
        background-color: transparent;
        width: 5px;
      }

      .side-resizer:hover,
      .side-resizer:active {
      
      
        border-right: 1px dashed #43676b;
      }

      .side-scroll-box {
      
      
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        overflow-y: auto;

        /* 火狐浏览器滚动条样式 */
        scrollbar-color: #bfbfbf rgb(239, 239, 239);
        scrollbar-width: thin;
      }

      /*滚动条样式*/
      .side-scroll-box::-webkit-scrollbar {
      
      
        width: 5px;
      }

      .side-scroll-box::-webkit-scrollbar-track {
      
      
        background: rgb(239, 239, 239);
        border-radius: 2px;
      }

      .side-scroll-box::-webkit-scrollbar-thumb {
      
      
        background: #bfbfbf;
        border-radius: 10px;
      }

      /* 拖动的时候禁用选择 */
      .sidebar-resizing {
      
      
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }

      .side-content {
      
      
        height: 120vh;
        background-color: #e9dfe5;
      }

      .home-main {
      
      
        /* 使用左外边距留出侧边栏宽度 */
        margin-left: var(--sidebar-width);

        background-color: #f5b1aa;
        height: 200vh;
      }
    </style>

    <div class="home">
      <aside class="home-side" id="sidebar">
        <div class="side-scroll-box">
          <div class="side-content"></div>
        </div>
        <div class="side-resizer" id="sidebar-resizer"></div>
      </aside>
      <main class="home-main"></main>
    </div>

    <script>
      const html = document.querySelector("html");
      const sidebarResizer = document.getElementById("sidebar-resizer");
      const sidebar = document.getElementById("sidebar");
      sidebarResizer.addEventListener("mousedown", initResize, false);

      function initResize(e) {
      
      
        window.addEventListener("mousemove", resize, false);
        window.addEventListener("mouseup", stopResize, false);
        html.classList.add("sidebar-resizing");
      }

      function resize(e) {
      
      
        var pos = e.clientX - sidebar.offsetLeft;
        pos = Math.min(pos, window.innerWidth - 100);
        document.documentElement.style.setProperty("--sidebar-width", pos + "px");
      }

      //on mouseup remove windows functions mousemove & mouseup
      function stopResize(e) {
      
      
        html.classList.remove("sidebar-resizing");
        window.removeEventListener("mousemove", resize, false);
        window.removeEventListener("mouseup", stopResize, false);
      }
    </script>

[Interpretación de los puntos principales] La barra lateral con ancho ajustable parece difícil en la superficie, pero todavía hay muchos detalles técnicos involucrados:

  • Diseño fijo de dos columnas

  • Variables CSS:--sidebar-width

  • Ajuste del estilo de la barra de desplazamiento

  • Eventos relacionados con el cambio de tamaño del ancho.

Diseño de tres columnas con posicionamiento fijo

El escenario de uso del diseño de tres columnas es generalmente los detalles del artículo, un lado es para operaciones como compartir y me gusta, y el otro lado es para contenido como recomendaciones, catálogos y anuncios. De hecho, el diseño de tres columnas no es difícil: puede implementar el diseño de dos columnas primero y luego implementar el diseño de tres columnas. Además de mostrarte el efecto del diseño de tres columnas, este caso también te muestra el efecto del diseño fijo. No puedes dejar de usar esta función en absoluto:

    <style>
      .home {
      
      
        display: flex;
        align-items: flex-start;
      }
      
      .left {
      
      
        width: 200px;
        flex-shrink: 0;

        background-color: #b98c46;
        height: 80vh;
        margin-right: 20px;
      }

      .right {
      
      
        width: 200px;
        flex-shrink: 0;
      }

      .main {
      
      
        flex: 1;
        display: flex;
      }

      .content {
      
      
        flex: 1;
        background-color: #8b968d;
        height: 300vh;
      }

      .box1 {
      
      
        width: 200px;
        flex-shrink: 0;
        height: 50vh;
        background-color: #aa4c8f;
        margin: 20px 20px;
      }

      .box2 {
      
      
        width: 200px;
        flex-shrink: 0;
        height: 30vh;
        background-color: #7a4171;
        margin: 20px 20px;

        position: sticky;
        top: 20px;
      }
    </style>

    <div class="home">
      <div class="left"></div>
      <div class="main">
        <div class="content"></div>
        <div class="right">
          <div class="box1"></div>
          <div class="box2"></div>
        </div>
      </div>
    </div>

Efecto:

inserte la descripción de la imagen aquí

[Interpretación de los puntos principales]

  • Estructura: contenido largo en el medio, anuncios (lavanda) y catálogo (morado oscuro) a la derecha
  • Cuando la barra de desplazamiento se deslice hacia abajo, el área del directorio permanecerá en la parte superior. El efecto de adsorción position: sticky;se implementa , y los principales navegadores actuales lo admiten bien1 .

diseño de cascada

El diseño en cascada se usa a menudo para sitios web de tipo imagen, por ejemplo: heaptang.com. El diseño de cascada tiene un nombre profesional en inglés, Masonry Layouts. El flujo de cascada, también conocido como diseño de flujo de cascada, es un método de diseño de página de sitio web popular. 2 .

Características del diseño de cascada:

1. Debido a que el flujo de la cascada es atractivo, el flujo de la cascada lo cargará continuamente con nueva información en la parte inferior de su página y atraerá su curiosidad al brindar imágenes visuales incompletas, de modo que no pueda detenerse y desee continuar explorando hacia abajo. . Los productos que utilizan esta solución a menudo pueden mejorar el tiempo de residencia del usuario a través del flujo de cascada y aumentar la viscosidad del usuario.

2. El modo de lectura rápida permite a los usuarios escanear una gran cantidad de información en poco tiempo, y el modo de carga diferida de la transmisión en cascada evita la operación de giro de clic y puede obtener la mayor experiencia de contenido al mínimo costo operativo, el La forma visual del flujo de la cascada facilita que las personas se sumerjan en ella y no es fácil que las interrumpan.

3. Además, la característica principal del flujo de cascada es: ancho fijo pero altura no fija. Este tipo de diseño de página es diferente del modo de diseño de imagen de matriz tradicional. Utiliza hábilmente la jerarquía visual y el flujo visual arbitrario para aliviar la fatiga visual.

El flujo de cascada es más adecuado para la navegación informal y los escenarios de uso sin propósito, como ir de compras, mirar mientras camina y, al mismo tiempo, sentirse atraído por la deslumbrante variedad de productos en la calle, por lo que es más adecuado para fotos, novelas, y escenas de información Tomando los casos exitosos existentes como ejemplo, muchos sitios web relacionados basados ​​en UGC están alojados en cascada.

inserte la descripción de la imagen aquí

Método 1, implementación de JavaScript

En la actualidad, no existe un método de implementación de CSS puro perfecto, y una solución madura requiere que JavaScript participe en la implementación 3 .

<style>
      .waterfall {
      
      
        position: relative;
      }
      .waterfall-item {
      
      
        position: absolute;
        width: 23%;
        height: 100px;
        background: rgb(236, 146, 10);
        margin-bottom: 10px;
        display: flex;
        justify-content: center;
        align-items: center;
        transition: all 0.1s;
      }

      .num {
      
      
        font-size: 18px;
        color: #fff;
        border-radius: 100%;
        width: 25px;
        height: 25px;
        line-height: 25px;
        text-align: center;
        border: 1px solid #fff;
      }
      .btn {
      
      
        text-align: center;
        font-size: 15px;
        color: #400eff;
        cursor: pointer;
        position: absolute;
        bottom: 10px;
        left: 50%;
      }
    </style>
    <div id="waterfall" class="waterfall"></div>
    <script>
      class WaterFall {
      
      
        constructor(container, options) {
      
      
          this.gap = options.gap || 0;
          this.container = container;
          this.items = container.children || [];
          this.heightArr = [];
          this.renderIndex = 0;
          window.addEventListener("resize", () => {
      
      
            this.renderIndex = 0;
            this.heightArr = [];
            this.layout();
          });
          this.container.addEventListener("DOMSubtreeModified", () => {
      
      
            this.layout();
          });
        }

        layout() {
      
      
          if (this.items.length === 0) return;
          const gap = this.gap;
          const pageWidth = this.container.offsetWidth;
          const itemWidth = this.items[0].offsetWidth;
          const columns = Math.floor(pageWidth / (itemWidth + gap)); // 总共有多少列

          while (this.renderIndex < this.items.length) {
      
      
            let top, left;
            if (this.renderIndex < columns) {
      
      
              // 第一行
              top = 0;
              left = (itemWidth + gap) * this.renderIndex;
              this.heightArr.push(this.items[this.renderIndex].offsetHeight);
            } else {
      
      
              const minIndex = this.getMinIndex(this.heightArr);
              top = this.heightArr[minIndex] + gap;
              left = this.items[minIndex].offsetLeft;
              this.heightArr[minIndex] += this.items[this.renderIndex].offsetHeight + gap;
            }
            this.container.style.height = this.getMaxHeight(this.heightArr) + "px";
            this.items[this.renderIndex].style.top = top + "px";
            this.items[this.renderIndex].style.left = left + "px";
            this.renderIndex++;
          }
        }

        getMinIndex(heightArr) {
      
      
          let minIndex = 0;
          let min = heightArr[minIndex];
          for (let i = 1; i < heightArr.length; i++) {
      
      
            if (heightArr[i] < min) {
      
      
              min = heightArr[i];
              minIndex = i;
            }
          }
          return minIndex;
        }

        getMaxHeight(heightArr) {
      
      
          let maxHeight = heightArr[0];
          for (let i = 1; i < heightArr.length; i++) {
      
      
            if (heightArr[i] > maxHeight) {
      
      
              maxHeight = heightArr[i];
            }
          }
          return maxHeight;
        }
      }

      window.onload = function () {
      
      
        const waterfall = document.getElementById("waterfall");
        const water = new WaterFall(waterfall, {
      
       gap: 10 });
        water.layout();
      };
    </script>

    <script>
      var index = 0;
      const waterfall = document.getElementById("waterfall");
      function getData(num = 5) {
      
      
        return new Promise((resolve, reject) => {
      
      
          setTimeout(() => {
      
      
            const fragment = document.createDocumentFragment();
            for (let i = 0; i < num; i++) {
      
      
              const div = document.createElement("div");
              const numDiv = document.createElement("div");
              div.className = "waterfall-item";
              numDiv.className = "num";
              numDiv.textContent = index + 1;
              index++;
              div.appendChild(numDiv);
              div.style.height = getRandomHeight(4, 1) + "px";
              fragment.appendChild(div);
            }
            waterfall.appendChild(fragment);
            resolve();
          }, 1000);
        });
      }

      getData(20);

      var loading = false;
      window.onscroll = async function () {
      
      
        const scrollTop = document.documentElement.scrollTop; // 滚动条位置
        const clientHeight = document.documentElement.clientHeight;
        const scrollHeight = document.body.scrollHeight; // 完整高度
        if (scrollTop + clientHeight >= scrollHeight && !loading) {
      
      
          loading = true;
          await getData();
          loading = false;
        }
      };

      function getRandomHeight(max = 5, min = 1) {
      
      
        return (Math.floor(Math.random() * (max - min + 1)) + min) * 100;
      }
    </script>

Método 2, Método futuro 4

.container {
    
    
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

artículo de referencia

♥ Soy ingeniero de front-end: tu amada Sen. Muchas gracias por sus gustos y atención. Todos son bienvenidos a participar en discusiones o colaboraciones. Grupo de intercambio QQ: 233589794.

★ Este artículo es de código abierto y utiliza el protocolo CC BY-SA 4.0 , indique la fuente para la reimpresión: Autocultivo de ingenieros front-end . GitHub.com@xiayulu.

★ Para obtener información sobre cooperación creativa o contratación, envíe un mensaje privado o envíe un correo electrónico a: [email protected], especificando el asunto: cooperación creativa o contratación de ingenieros de front-end .


  1. MDN. posición _ ↩︎

  2. Gulenjing. Análisis del principio de diseño e implementación del flujo de cascada . Blog Garden. ↩︎

  3. Front-end avanzado Xiaobai ¡ Productos secos! Complemento de diseño de flujo de cascada del paquete js puro . Pepitas de tierras raras. ↩︎

  4. MDN. Disposición de mampostería . ↩︎

Supongo que te gusta

Origin blog.csdn.net/hongshuteng/article/details/127482268
Recomendado
Clasificación