由于渲染计时,可以访问useref()值

发布于 2025-01-21 10:59:46 字数 722 浏览 0 评论 0原文

我是反应的新手。我也是在这个论坛上问问题的新手。

我有一个相当基本的两列布局,我正在尝试在RH列中动态设置图像大小,以匹配LH列的文本内容的高度。

我已经弄清楚我无法在页面渲染之前获得参考元素的滚动值,但是我不想渲染页面,直到我知道滚动值以呈现图像...我去。

如果我将console.log放入usefeffect(),但我不知道要适应它以帮助我解决特定问题,我可以获得ref'D值。

谁能帮助实现同样想法的解决方案或其他方法?

const tickList = useRef();


useEffect(() => {
  console.log(tickList);
}, [])


<div className='ticklist-container' ref={tickList}>
        <TickCrossList items={tickListItems} />
      </div>


<div className='image-container p-1 flex flex-center'>
        <img
          src={imageUrl}
          alt={imageAltText}
          style={{ width: tickList.current.scrollHeight * 1.77 }}
        />
      </div>

I am fairly new to React. I am also new to asking questions on this forum.

I have a pretty basic two column layout and I am trying to dynamically set the image size in the RH column to match the height of the text content of the LH column.

I have figured out I can't get the scrollHeight value of the ref'd element until the page is rendered but I don't want to render the page until I know the scrollHeight value to render the image...and around in circles I go.

I can get the ref'd value if I put a console.log inside a useEffect() but I don't know to adapt this to help me solve the specific problem.

Can anyone help with a solution or another method to achieve this same idea?

const tickList = useRef();


useEffect(() => {
  console.log(tickList);
}, [])


<div className='ticklist-container' ref={tickList}>
        <TickCrossList items={tickListItems} />
      </div>


<div className='image-container p-1 flex flex-center'>
        <img
          src={imageUrl}
          alt={imageAltText}
          style={{ width: tickList.current.scrollHeight * 1.77 }}
        />
      </div>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诗笺 2025-01-28 10:59:46

我相信这是一个XY问题。您正在问如何在技术上完成几乎不可能的任务(1)当您实际试图回答另一个问题时:如何使某些文本和图像并排看起来不错(2)(2)不是实际的编码问题 - 这是一个图形设计问题)。

最值得注意的是,您没有提供文本或图像,因此您要提供一个一般解决方案,在所有情况下都可以使用。该解决方案不存在。图片如果文本长1个字母,则结果如何,如果长2页长。

最后但并非最不重要的一点是,问题与反应并不严格。通常,您应该问自己:

  • 这是可以在DOM(HTML + CSS + JS)中实现的吗?
  • 它需要JS吗?
  • 一旦用“是” 回答以上两个,并且您知道输出的外观,反应部分通常很容易。

更详细地...

(1)。当您更改图像大小时,只要保持其比率,就会影响该段落的宽度,导致其重新编写,更改其高度,并可能创建循环。在许多情况下,您需要多次重新运行脚本,直到调整图像高度时文本不再重写。

  1. 在某些情况下,根据文本的数量,解决方案甚至都不存在。
  2. 在其他情况下,脚本将在两个位置之间跳跃,基本上是两个不同数量的文本行,每个行调整了图像大小,导致文本跳到其他行,导致整个事物无限期地颤抖。实际上,我已经在生产网站上看到了很多次。一般修复是记录每个调整大小的步骤,如果脚本获得以前的任何值,请杀死它。一个丑陋的错误修复程序。
  3. 而且,在其他情况下,您可能会发现多种可能的“解决方案”。脚本应该选择哪一个?

在调整事件大小的背景下(用户将平板电脑从景观翻转到肖像和背部)的上下文中,您会得到灾难的秘诀。

更不用说浏览器如今允许用户覆盖字体大小或字体家庭,从而控制可读性。您的脚本如何应对此更改?


(2)这个问题通常是解决的。

有一些不同的考虑因素:

  • 图像需要具有最小尺寸,在该大小中,它传达了任何消息。它需要始终保持“可读性”。不太小,但也不太大。它必须与文本数量保持平衡。
  • 如果文本过多,则可以使其盒子滚动(取决于情况),要么将图像的侧面裁剪(如果图像是“裁剪” - 从图形POV中)。
  • 文本需要始终保持可读(线条不应太长或太短)
  • ,通常通常要大致确定最小图像大小和段落宽度之间的比例,并设置一致的宽度两者之间的比率(在整个应用程序/网站中)(设计一致性在您的网站整体上的看法是有回报的 - 如果正确完成时,它提供了节奏和整体信心和可靠性的感觉)。根据段落的长度和可读性,使用1:1、2:1、3:1、1:2、1:3。另一个良好比例是1:1.618(黄金比率 - 令人愉悦的眼睛,没有确切的解释 - 调试人类特别困难)
  • 一个典型的解决方案是将段落包裹在一个稍大,可见的盒子中,背景略有不同或边框颜色。这使您在匹配图像高度方面具有更大的灵活性。请参阅下面的示例。
  • 在特定的容器宽度下方,您希望将两个元素(图像和文本框)包裹起来,因此它们都可以阅读且有吸引力(例如:响应能力),

您可能想避免使用一些不好的例子(但是您当前正在询问),然后对Y问题有一个可能的答案:

.container {
  display: flex;
  max-width: 600px;
  margin: 0 auto;
  margin-top: 1rem;
  justify-content: space-between
}

.proper img {
  width: 50%;
}
.proper div {
  background-color: #F5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2em;
}
.proper.two div {
  background-color: transparent;
  border: solid #ddd;
  border-width: 1px 0 1px 1px;
}
<div class="container">
  <h3>What you probably don't want</h3>
</div>
<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="max-width: 528px">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="max-width: 515px">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="height: 1em">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. More Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="height: 2em">
</div>

<div class="container">
  <h3>What you probably want</h3>
</div>
<div class="container proper">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg">
</div>
<div class="container proper two">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg">
</div>


作为奖励,黄金比率可以为您做什么:

* {
  box-sizing: border-box;
}
body {
  background-color: #f5f5f5;
  margin: 0;
  padding: 0 2.1rem;
}
.container {
  padding: 2.1rem 0;
  max-width: 500px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.golden-ratio {
  border-radius: .35rem;
  overflow: hidden;
  display: flex;
  justify-content: space-between;
  background-color: white;
  color: #aaa;
  aspect-ratio: 1.618;
  box-shadow: 0 1px 5px 0 rgb(0 0 0 / 10%), 0 2px 2px 0 rgb(0 0 0 / 07%), 0 3px 1px -2px rgb(0 0 0 / 06%)
}
.image-container {
  flex-grow: 1;
  background: #ddd url('https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg') 100% /cover;
}
.content {
  flex: 0 0 61.8%;
  font-size: 1.5rem;
  font-style: italic;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10%;
}

@media (max-width: 600px) {
  .golden-ratio {
    flex-direction: column-reverse;
    aspect-ratio: unset;
  }
  .content {
    flex-basis: 50%;
    padding: 3rem;
    font-size: 1.2rem;
  }
  .image-container {
    aspect-ratio: 4.16;
    flex-basis: 50%;
  }
}
<div class="container">
  <div class="golden-ratio">
    <div class="content">Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
    <div class="image-container"></div>
  </div>
</div>

I believe this is, at core, an XY problem. You're asking how to technically achieve a nearly impossible task (1) when you're actually trying to answer another question: how to make some text and an image look good side by side (2) (which, by and large, is not an actual coding problem - it's a graphical design problem).

Most notably, you're not providing either the text or the image, so you're asking for a general solution, which would work in all cases. That solution doesn't exist. Picture how the result would look if the text was 1 letter long and how it would look if it was 2 pages long.

Last, but not least, the problem is not strictly related to React. In general, you should ask yourself:

  • is this achievable in DOM (HTML + CSS + JS)?
  • does it need JS?
  • once you answer both of the above with "yes", and you know how the output should look like, the React part is generally easy.

In more detail...

(1). When you're changing the image size, provided you maintain its ratio, you're going to affect the paragraph's width, causing it to re-wrap, changing its height, potentially creating a loop. In many cases, you'd need to re-run the script multiple times until the text no longer re-wraps when adjusting the image height.

  1. In some cases, depending on the amount of text, a solution doesn't even exist.
  2. In other cases, the script will jump between two positions, basically two different numbers of text rows, each resizing the image, causing the text to jump to the other number of rows, causing the whole thing to tremble indefinitely. I've actually seen this quite a few times, on production websites. The general fix is to record each resizing step and, should the script get any of the previous values, kill it. An ugly fix for an ugly bug.
  3. And, in some other cases, you might find multiple possible "solutions". Which one should the script pick?

Picture all this in the context of resize events (a user flipping their tablet from landscape to portrait and back) and you got a recipe for disaster, UX-wise.

Not to mention browsers nowadays allow users to override font-size or font-family, giving control over readability. How would your script cope with this change?


(2) How this problem is typically solved.

There are a few distinct considerations:

  • the image needs to have a minimum size, at which it conveys whatever message it carries. It needs to remain "readable" at all times. Not too small, but not too large, either. It has to be in balance with the amount of text.
  • if there's too much text, you either make its box scrollable (depending on case) or you crop the sides of the image (if image is "croppable" - from a graphical POV).
  • the text needs to remain readable (with ease) at all times (lines shouldn't be too long or too short)
  • typically, you want to roughly determine a ratio between the minimal image size and a paragraph width good for readability and set a consistent ratio (throughout the whole app/website) between the two (design consistency pays off in how your website is perceived as a whole - it provides rhythm and an overall feeling of confidence and reliability, when done right). Go with 1:1, 2:1, 3:1, 1:2, 1:3, based on paragraph length and readability. Another good ratio is 1:1.618 (the golden ratio - it's pleasing to the eye, without an exact explanation - debugging humans is particularly difficult)
  • a typical solution is to wrap the paragraph into a slightly bigger, visible box, with a slightly different background or border color. This gives you significantly more flexibility in matching the image height. See the examples below.
  • below a particular container width, you want the two elements (the image and the text box) to wrap, so they both remain readable and attractive (e.g: responsiveness)

A few bad examples you probably want to avoid (but you're currently asking for), followed by a possible answer to the Y problem:

.container {
  display: flex;
  max-width: 600px;
  margin: 0 auto;
  margin-top: 1rem;
  justify-content: space-between
}

.proper img {
  width: 50%;
}
.proper div {
  background-color: #F5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2em;
}
.proper.two div {
  background-color: transparent;
  border: solid #ddd;
  border-width: 1px 0 1px 1px;
}
<div class="container">
  <h3>What you probably don't want</h3>
</div>
<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="max-width: 528px">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="max-width: 515px">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="height: 1em">
</div>

<div class="container">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. More Beer!
  </div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg" style="height: 2em">
</div>

<div class="container">
  <h3>What you probably want</h3>
</div>
<div class="container proper">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg">
</div>
<div class="container proper two">
  <div>Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
  <img src="https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg">
</div>


As a bonus, what golden ratio can do for you:

* {
  box-sizing: border-box;
}
body {
  background-color: #f5f5f5;
  margin: 0;
  padding: 0 2.1rem;
}
.container {
  padding: 2.1rem 0;
  max-width: 500px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.golden-ratio {
  border-radius: .35rem;
  overflow: hidden;
  display: flex;
  justify-content: space-between;
  background-color: white;
  color: #aaa;
  aspect-ratio: 1.618;
  box-shadow: 0 1px 5px 0 rgb(0 0 0 / 10%), 0 2px 2px 0 rgb(0 0 0 / 07%), 0 3px 1px -2px rgb(0 0 0 / 06%)
}
.image-container {
  flex-grow: 1;
  background: #ddd url('https://random-ize.com/lorem-ipsum-generators/beer/suds3.jpg') 100% /cover;
}
.content {
  flex: 0 0 61.8%;
  font-size: 1.5rem;
  font-style: italic;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10%;
}

@media (max-width: 600px) {
  .golden-ratio {
    flex-direction: column-reverse;
    aspect-ratio: unset;
  }
  .content {
    flex-basis: 50%;
    padding: 3rem;
    font-size: 1.2rem;
  }
  .image-container {
    aspect-ratio: 4.16;
    flex-basis: 50%;
  }
}
<div class="container">
  <div class="golden-ratio">
    <div class="content">Spiff up your work with our random beer Lorem Ipsum generator. Beer!</div>
    <div class="image-container"></div>
  </div>
</div>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文