score:1

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>


Related Query

More Query from same tag