How to have vertically centered text wrap around a floating image

Viewed 131

I'm not entirely sure how to describe it better than the title, so I'll just draw it.

In the below images, the horizontal lines are the "text", the small box is the image, and the bigger box is the whole webpage. I want the text to behave like it does in the drawings and I have no idea how.

vertically centered text next to an image

text wrapping around a floating image

I can get the text to wrap around the image using float, and i can get the text vertically centered using flexbox or grid or table, but i can't do both at the same time. Using any of those techniques to vertically center the text appears to encounter the clearing bug and they basically treat height:100% as if the image wasn't there.

parent of text that needs to be vertically centered obeys clearfix

child does not obey clearfix

3 Answers

CSS Exclusions would help here: it allows you to wrap text around any element, including an absolutely positioned element. Unfortunately, this spec is still a working draft, and no browsers support it yet.

Here is a snippet to illustrate how CSS Exclusions would be useful to you. As you can see, it uses absolute positioning rather than a float, and everything works as you want it to, except that the text does not wrap. The exclusion rule wrap-flow has no effect, sadly.

.d1 {
    position: relative;
    border: 2px solid cyan;
    min-height: 200px;
    margin-bottom: 2em;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 1em;
}
.excl {
    position: absolute;
    top: 0;
    right: 0;
    width: 100px;
    height:200px;
    background-color: lime;
    wrap-flow: both;
}
<div class="d1">
    <div class="excl"></div>
    <div class="txt">
        <p>
            Lorem ipsum 
        </p>
        <p>
            Nunc eu 
        </p>
    </div>
</div>
<div class="d1">
    <div class="excl"></div>
    <div class="txt">
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse odio massa, tempor auctor posuere et, consequat non velit. Suspendisse potenti. Proin hendrerit eu neque id varius. Morbi consequat dui neque, non fringilla dolor pretium vitae. Pellentesque congue nec justo vel mattis. Fusce lobortis turpis a urna elementum eleifend. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla rhoncus sagittis lacus at dignissim.
        </p>
        <p>
            Nunc eu rhoncus massa. Nam pretium pellentesque faucibus. Mauris fringilla erat et nunc feugiat hendrerit. Nullam bibendum faucibus quam ut rhoncus. Maecenas non orci dui. Suspendisse maximus feugiat augue, sit amet ultrices arcu egestas at. Phasellus eget libero purus. Suspendisse potenti. Nulla vestibulum diam at pharetra vehicula. Donec quis dignissim tellus. In dictum sagittis ex, euismod ultricies leo tempor vel.
        </p>
        <p>
            Donec consectetur facilisis neque, eu dignissim massa interdum vel. Fusce vestibulum libero a ex malesuada, et pharetra risus gravida. Duis vehicula, dolor ut mattis sagittis, metus ex lacinia velit, sed interdum magna nisi eu magna. Aenean porttitor pulvinar lectus, sit amet efficitur ligula suscipit ut. Vivamus lobortis, felis at ultrices eleifend, risus ex ullamcorper lacus, nec aliquam orci sapien vitae elit. Suspendisse vitae nunc ante. Curabitur consequat diam et enim varius, quis mattis lectus posuere. Quisque sollicitudin, eros ut aliquet gravida, ipsum lectus consequat arcu, ac congue libero ante nec tellus. Mauris massa dolor, dapibus a metus eu, vehicula ultricies justo. Integer eu turpis non mauris finibus congue. Donec rhoncus felis in elit tempor lacinia. Ut placerat sodales libero, in laoreet nibh commodo quis.
        </p>
        <p>
            Aliquam in lacus tempor, viverra quam in, interdum lorem. Aliquam bibendum, sem eget egestas iaculis, velit urna finibus est, a dapibus nulla orci at nibh. Cras eget ullamcorper nisl. Vivamus maximus, lorem a rutrum semper, eros orci auctor urna, a pharetra enim felis id arcu. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam vitae consequat ipsum. Quisque egestas viverra elit, vel pulvinar enim. Vestibulum faucibus mattis sem sed placerat. Fusce pretium, mauris eget facilisis lobortis, lectus enim finibus lacus, a finibus orci odio at ante. Nullam non tincidunt turpis, ut tempor dolor. Aliquam sit amet augue eu orci cursus pulvinar eleifend et lacus. Nam imperdiet lectus quis urna fringilla convallis. Mauris pretium fringilla iaculis. Donec volutpat lacus urna, in convallis nisi tincidunt luctus. Maecenas ut augue metus. Aenean ornare erat eu auctor volutpat.
        </p>
        <p>
            Praesent a odio enim. Proin tincidunt vulputate nibh, eget rhoncus arcu vulputate ultricies. Etiam nec magna nec est pharetra aliquet. Vivamus rhoncus convallis lectus at rhoncus. Nam elit risus, volutpat sit amet erat sit amet, fringilla tempus erat. Donec id diam sodales metus rutrum molestie eu ac erat. Mauris condimentum erat nec leo venenatis sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin quis sem mattis, pellentesque dui id, imperdiet justo. Donec id iaculis ante. Morbi maximus nibh eget convallis cursus. Suspendisse tristique felis et tempus vulputate. Morbi id tincidunt sem, eget vestibulum tortor.
        </p>
    </div>
</div>

In the meantime, one suggestion would be to use a flexbox when you only have a small amount of text to go beside the image, and use a float when you have more text to go there. Otherwise you will simply have to choose between float or flex and live with it not looking quite right, or go for a different look.

You can achieve with help of float and flex properties. So you will need to check dynamically small amount of text if exist then add .box-flex class in .box if amount of text is more then don't need to add .box-flex class.
With flex display I am using order property for transform image div from left to right.

I hope below snippet will help you a lot.

*{box-sizing: border-box;}
.box{
    font-family: Arial;
    font-size: 16px;
    line-height: 22px;
    width: 100%;
    max-width: 480px;
    min-height: 100px;
    background-color: rgb(148, 206, 203);
    padding: 15px;
    margin: 15px auto 15px auto;
    color: #333;
    border-radius: 8px;
}
.img{
    width: 100px;
    height: 100px;
    min-width: 100px;
    max-width: 100px;
    max-height: 100px;
    background: coral;
    margin-left: 12px;
    float: right;
    border-radius: 4px;
}
.txt{
    position: relative;
    min-height: inherit;
    padding: 0;
    text-align: justify;
}
.box-flex{
    display: flex;
    justify-content: space-between;
}
.box-flex .img{
    order: 1;
}
.box-flex .txt{
    padding: 0;
    align-self: center;
    min-height: auto;
}
<div class="box box-flex">
    <div class="img"></div>
    <div class="txt">
        If small amout of text (use .box-flex)
    </div>
</div>
<div class="box">
    <div class="img"></div>
    <div class="txt">
        Lorem ipsum dolor sit amet conse ctetur adipis icing elit. Unde adipisci soluta beatae minima, dolores atque voluptas, explicabo mollitia, sunt alias nihil dolo ribus veritatis perfe rendis quib usdam error exerci ationem quia conseq uuntur eos digni ssimos sed veniam? Rerum saepe qui sed corporis volupt atibus soluta quo eaque. Quidem recu sandae dolorum nesciunt Rerum saepe qui sed.
    </div>
</div>

you can use position : relative (for the text) top:50% transform:translateY(-50%)

this will center the text at the center of the div vertically or you can use the vertical allign for both image and text vertical-allign: middle

i don't know if i just answered your question or something is missing. let me know if it doesn't work to fix this again.

Related