响应式/流体设计:使用线性插值进行布局 [英] Responsive/Fluid Design: Using Linear Interpolation for Layout

查看:21
本文介绍了响应式/流体设计:使用线性插值进行布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试做类似的事情:CSS Poly Fluid Sizing using calc()、vw、断点和线性方程

  • 对于 600 像素或更小的视口,包装器应为 100%.
  • 对于 1800 像素的视口,包装器应跨越 70%.
  • 所有剩余视口的内插值.

这是我目前想到的:

    #square1 {
        background-color: blue;
        margin: 10px 0;
        width: 100%;
        height: 50px;
    }
    
    #square2 {
        background-color: yellow;
        margin: 10px auto;
        width: calc(100% - 20 * (100vw - 600px)/40);
        height: 50px;
    }
    
    #square3 {
        background-color:green;
        margin: 10px auto;
        width: calc(100% - 20 * (max(100vw, 600px) - 600px)/40);
        height: 50px;
    }
    
    #square4 {
        background-color: red;
        margin: 10px auto;
        width: calc(min(100vw, (100% - 20 * (100vw - 600px)/40)));
        height: 50px;
    }

<div id="square1"></div>
<div id="square2"></div>
<div id="square3"></div>
<div id="square4"></div>

Square 1 仅供参考.

Square 2 以某种方式起作用,但只是因为我任意乘以因子 20.为什么有效?

Square 2 works somehow but only because I multiplied by factor 20 arbitrarily. Why does it work?

Square 3 和 4 应避免在视口小于 600 像素的情况下水平溢出.这两种解决方案都不起作用.

Square 3 and 4 shall avoid a horizontal overflow in case that the viewport is smaller than 600px. Both solutions don't work.

Fiddle 链接这里

有什么想法吗?谢谢.

PS:我不专业.

推荐答案

这个问题的简短回答是:

/* for IE, Opera, Android and older browsers */
.rectangle { width: calc(55vw + 270px) }
@media (max-width:  600px) { .rectangle { width: 100% } }
@media (min-width: 1800px) { .rectangle { width:  70% } }

/* modern browsers */
.rectangle { width: max(70%, min(100%, calc(55vw + 270px))) }

为了能够使用'线性方程',我们需要两个点,p1(x1,y1)p2(x2,y2)strong>,在 XY 空间中,描绘了最小和最大视口尺寸下的最小和最大尺寸.

To be able to use a 'Linear Equation' we need two points, p1(x1,y1) and p2(x2,y2), in an XY-space which depict a minimum and a maximum size at minimum and maximum viewport size.

幸运的是 OP 给了我们一些限制:

Fortunately the OP gave us a few constraints:

  • 视口宽度 <= 600px,元素宽度 100%
  • 视口宽度 >= 1800px,元素宽度 70%
  • 视口宽度 > 600px 和 <1800px,元素宽度用线性方程计算

使用这些约束,我们可以定义线性方程所需的两个点:

Using those constrainsts, we can define the required two points we need for the linear equation:

  • 在视口宽度 600px = x1 处,元素宽度为 100%(600px 为 600px = y1)
  • 在视口宽度 1800px = x2 处,元素宽度为 70%(1800px 为 1260px = y2)
  • at viewport width 600px = x1 the element width is 100% (of 600px is 600px = y1)
  • at viewport width 1800px = x2 the element width is 70% (of 1800px is 1260px = y2)

我们有两个等式可供使用:

We have two equations at our disposal:

  1. Y 截距形式:y = mx + b
  2. 点斜率形式:y = y1 + m(x - x1)

(查看MathIsFun:直线方程,通俗易懂的中学解说,值得一读.

(check out MathIsFun: Equation of a Straight Line, easy to understand Middle School explanations, well worth the read).

哪里

  • m = (y2 - y1)/(x2 - x1)

x = 始终定义为 100vmin、vw、vh 或 vmax,具体取决于:

  • 视口宽度/高度独立的结果(例如字体大小、填充、边距)
  • 视口宽度或高度相关的结果(例如宽度、高度、填充、边距)

b = y1 - m * x1(见中页:https://mathforum.org/library/drmath/view/52848.html)

替换

  1. y = (y2 - y1)/(x2 - x1) * x + (y - (y2 - y1)/(x2 - x1) * x1)
  2. y = y1 + (y2 - y1)/(x2 - x1) * (x - x1)

完全替代,点斜率形式"是最短的,但为了节省 CPU 负载,我选择进行一些手动计算并在我的最终 CSS 中使用 Y 截距形式 calc().

Fully substituted, 'point slope form' is the shortest, but to save on CPU load, I have opted to do some manual calculations and use the Y-intercept form in my final CSS calc().

通过使用点p1(600,600)p2(1800,1260)手动计算'm''b' 我们将产生可以在 CSS calc() 中使用的最终方程:

By manually calculating 'm' and 'b' using points p1(600,600) and p2(1800,1260) we will yield the final equation we can use in CSS calc():

  • m = (1260 - 600)/(1800 - 600) = 0.55
  • b = 600 - 0.55 * 600 = 270
  • y = mx + b 变为:y = 0.55x + 270(最终方程)
  • m = (1260 - 600) / (1800 - 600) = 0.55
  • b = 600 - 0.55 * 600 = 270
  • y = mx + b becomes: y = 0.55x + 270 (final equation)

width 在这种情况下取​​决于视口宽度,因此我们使用视口单位 vw 作为 'x'

width is in this case viewport width dependent, so we use viewport unit vw for 'x'

.rectangle { width: calc(0.55 * 100vw + 270px) } /* initially */
.rectangle { width: calc(55vw + 270px) }         /* simplified */

/* with min/max constraints */
.rectangle { width: max(70%, min(100%, calc(55vw + 270px))) }

代码片段

var root      = document.documentElement;
var body      = document.body;
var rectangle = document.getElementById('demo');

// Polyfill FOR IE11, used for rounding
if (Number.EPSILON === undefined) { Number.EPSILON = Math.pow(2, -52); }

function updateSpecs() {
var txt = "<table><tbody>";
    txt += "<tr><td><b>#demo width/height<sup>*</sup></b>:" + "</td><td>" + rectangle.clientWidth + "/" + Math.round(((rectangle.clientWidth/root.clientWidth*100) + Number.EPSILON) * 1000) / 1000 + "%</td></tr>";
    txt += "<tr><td><br></tr>";
    txt += "<tr><td>Screen width/height:"        + "</td><td>" + screen.width       + "*" + screen.height      + "</td></tr>";
    txt += "<tr><td>window width/height:"        + "</td><td>" + window.innerWidth  + "*" + window.innerHeight + "</td></tr>";
    txt += "<tr><td><br></tr>";
    txt += "<tr><td>HTML width/height:"          + "</td><td>" + root.clientWidth   + "*" + root.clientHeight  + "</td></tr>";
    txt += "<tr><td>BODY width/height:"          + "</td><td>" + body.clientWidth   + "*" + body.clientHeight  + "</td></tr>";
    txt += "<tr><td><br></tr>";
    txt += "<tr><td colspan='2'><b><sup>*</sup></b>check width 600px and 1800px</tr>";
    txt += "</tbody></table>";

    document.getElementById("specs").innerHTML = txt;
}

updateSpecs() // first run

window.addEventListener('resize', updateSpecs);

/**************************/
/* preferred global rules */
/**************************/
html,body               { box-sizing: border-box; width: 100%; max-width: 100%; margin: 0 }
*::before,*::after, *   { box-sizing: inherit }

/* debugging output */
#specs { width: 100%; padding: 5rem; font-family: monospace }

/* rectangle eye-candy only */
.rectangle { background-color: purple; margin: 10px auto; height: 50px }

/* use of linear equation */
/* CSS for IE, Opera, Android and older browsers */
.rectangle { width: calc(55vw + 270px) } /* p1(600,600) p2(1800,1260) */
@media (max-width:  600px) { .rectangle { width: 100% } }
@media (min-width: 1800px) { .rectangle { width:  70% } }

/* CSS for modern browsers, no @media required */
#rectangle { width: max(70%, min(100%, calc(55vw + 270px))) }

/*
    NO MORE CSS BELOW THIS LINE, explanation and examples only
*/
/*
    LINEAR EQUATION, generic math
    math reference: https://www.mathsisfun.com/equation_of_line.html

    USING POINTS
        p1(x1,y1) - 1st point on an YX-graph => minimum viewport size, min required size limit 
        p2(x2,y2) - 2nd point on an YX-graph => maximum viewport size, max required size limit 

        parameter definition:
        p1(vp_minimum, size_at_vp_minimum)
        p2(vp_maximum, size_at_vp_maximum)

    WHERE
        x-axis: viewport size (either width or height of the browser window, device pixel, etc.)
        y-axis: required size (of font, width, height, padding, margin, etc.)

    CALCULATE
        y = required responsive size, the CSS calc() result

    WITH EITHER EQUATION
        1) point slope form: y - y1 = m(x - x1)
            simplified  y = y1 + m(x - x1)
            substituted y = y1 + (y2 - y1) / (x2 - x1) * (x - x1)

        2) y-intercept form: y = mx + b
            substituted y = (y2 - y1) / (x2 - x1) * x + (y1 - (y2 - y1) / (x2 - x1) * x1)

        where
            m = (y2 - y1) / (x2 - x1)

            x = always defined as 100vmin,vw,vh or vmax depending on:
                - viewport width/height independent result (e.g. fontsize, padding, margin)
                - either viewport width or height dependent result (e.g. width, height, padding, margin) 

            b = y1 - m * x1 (see halfway: http://mathforum.org/library/drmath/view/52848.html)

    RESULTING CSS 
        use either of six variations depending on
         - pre calculated values
         - SCSS pre-processor
         - CSS custom variables
         - CPU load

        vx = is either 100vmin,vw,vh or vmax

        1) point slope form
            a) calc( y1 + m * (100vx - x1) ) or
            b) calc( y1 + (y2 - y1) / (x2 - x1) * (100vx - x1) )

        2) y-intercept form
            a) calc( m * 100vx + b )
            b) calc( m * 100vx + (y1 - m * x1) )
            c) calc( (y2 - y1) / (x2 - x1) * 100vx + b )
            d) calc( (y2 - y1) / (x2 - x1) * 100vx + (y1 - (y2 - y1) / (x2 - x1) * x1) )

    NOTE: simplify 'mx' in (m * 100vx) by multiplying m * 100 and then use the vmin,vh,vw,vmax unit
          e.g. y = 0.01 * 100vw =>  y = 1vw  
*/

/* 
    LINEAR EQUATION, specific math for Stackoverflow question 54969190

    points p1(x1= 600,y1= 600) where x1 =  600px (min vp) and y1 =  600 = 100% of  600 (width at vp  600px)
           p2(x2=1800,y2=1260) where x2 = 1800px (max vp) and y2 = 1260 =  70% of 1800 (width at vp 1800px)

    Using y-intercept form 'y=mx+b' and manually calculating 'm' and 'b' our final equation will be

    m = (1260 - 600) / (1800 - 600) = 0.55
    b = 600 - 0.55 * 600 = 270
    y = 0.55x + 270

    'width' is in this case viewport width dependent, so use viewport unit VW for 'x'

    => CSS calc(0.55 * 100vw + 270px)
    => simplified calc(55vw + 270px)

    All below CSS calculation yield the same value for 'width'
*/
/* 1a) *//* width : max(70%, min(100%, calc(600px + 0.55 * (100vw - 600px))));/**/
/* 1b) *//* width : max(70%, min(100%, calc(600px + (1260 - 600) / (1800 - 600) * (100vw - 600px))));/**/
/* 2a) *//* width : max(70%, min(100%, calc(55vw + 270px))); /* preferred, least CPU intensive */
/* 2b) *//* width : max(70%, min(100%, calc(0.55 * 100vw + (600 - 0.55 * 600) * 1px)));/**/
/* 2c) *//* width : max(70%, min(100%, calc((1260 - 600) / (1800 - 600) * 100vw + 270px)));/**/
/* 2d) *//* width : max(70%, min(100%, calc((1260 - 600) / (1800 - 600) * 100vw + (600 - (1260 - 600) / (1800 - 600) * 600) * 1px)));/**/

<div id="demo" class="rectangle"></div>
<div id="specs"></div>

这篇关于响应式/流体设计:使用线性插值进行布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆