自适应/流体设计:使用线性插值进行布局

问题描述 投票:1回答:1

我试图做类似的事情:CSS Poly Fluid Sizing using calc(), vw, breakpoints and linear equations

  • 对于600像素或更小的视口,包装器应跨越100%。
  • 对于1800px的视口,包装器应占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>

平方1仅供参考。

Square 2以某种方式起作用,但这仅是因为我任意乘以20倍。为什么有效?

如果视口小于600px,

平方3和4应避免水平溢出。两种解决方案都不起作用。

链接到小提琴here

有什么想法吗?谢谢。

PS:我不是专业人士。

html css responsive-design linear-interpolation
1个回答
0
投票

这个问题的简短答案是:


/* 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))) }

为了能够使用'Linear Equation',我们在XY空间中需要两个点,分别是p1(x1,y1)p2(x2,y2)最小和最大视口大小的最小和最大大小。

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

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

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

  • 在视口宽度600px = x1时元素宽度为100%(600px为600px = y1
  • 在视口宽度1800px = x2时,元素宽度为70%(1800px为1260px = y2

我们有两个方程式可供使用:

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

((请签出[[MathIsFun: Equation of a Straight Line,易于理解的中学解释,非常值得阅读)。

where

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

  • x =始终定义为100vmin,vw,vh或vmax

  • ,具体取决于:
      视口宽度/高度无关的结果(例如,字体大小,填充,边距)
    • 视口宽度或高度相关的结果(例如,宽度,高度,填充,边距)
  • b = y1-m * x1

  • (请参阅中途页面:https://mathforum.org/library/drmath/view/52848.html
取代

    y =(y2-y1)/(x2-x1)* x +(y-(y2-y1)/(x2-x1)* x1)
  1. y = y1 +(y2-y1)/(x2-x1)*(x-x1)
  • 完全替换的“点斜率形式”是最短的,但是为了节省CPU负载,我选择进行一些手动计算,并在最终的CSS

    calc()

  • 中使用Y-intrecept形式。通过使用点[[p1(600,600)

    p2(1800,1260)手动计算'm''b',我们将得出可以使用的最终方程在CSS calc()

    m =(1260-1600)/(1800-600)= 0.55
      b = 600-0.55 * 600 = 270
    • y = mx + b变为:
    • y = 0.55x + 270
    (最终方程)
  • width在这种情况下取​​决于视口宽度,因此我们对'x'使用视口单位vw

    .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>
  • © www.soinside.com 2019 - 2024. All rights reserved.