Well, apparently a plain CSS solution isn't possible; and I remember seeing elsewhere on this site a JS solution that does text breaking, but I couldn't apply it to my problem at the time, so I forgot the reference - so now I rolled my own, which at least has plenty of console.log
throughout.
So, here is my solution, that does exactly what I wanted:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="/media/Data1/work/bbs/gits/econdk-vis-01_git/jquery-1.12.3.min.js"></script>
<style type="text/css">
.a1 {
border-style: solid;
border-width: 1px;
font-size: 1em;
line-height: 1.25em;
height: 2.5em;
max-height: 2.5em;
}
</style>
<script type="text/javascript">
// see SO: 1582534
$.fn.getWidthSingleLine = function(){
var contents = this.contents(),
wrapper = '<span style="display: inline-block; white-space: nowrap;" />',
width = '';
contents.wrapAll(wrapper);
//contents.parent().css("white-space", "nowrap"); // try this, instead of setting unreasonable large width? ok - though set explicitly above
var fontsize = parseFloat( contents.parent().css("font-size") ); //px
width = contents.parent().width(); // parent is now the wrapper
contents.unwrap();
return {
widthpx: width,
widthem: width / fontsize
};
}
$.fn.getHeightFromWidth = function(inwidth){
var contents = this.contents(),
wrapper = '<span style="display: inline-block;" />',
width = '';
contents.wrapAll(wrapper);
contents.parent().width(inwidth); // parent is now the wrapper
var fontsize = parseFloat( contents.parent().css("font-size") ); //px
height = contents.parent().height(); // parent is now the wrapper
contents.unwrap();
return {
heightpx: height,
heightem: height / fontsize
};
};
ondocready = function() {
var retwobj = $("#txtest").getWidthSingleLine();
console.log( retwobj.widthem + " em " + retwobj.widthpx + " px ; docw " + $(document).width() + " winw " + $(window).width() );
var findwidthpx = retwobj.widthpx/2;
var rethobj = $("#txtest").getHeightFromWidth( findwidthpx );
// note: $("#txtest").css("max-height")) is in pixels!
var maxh = parseFloat( $("#txtest").css("max-height") );
var hdiffpx = rethobj.heightpx - maxh;
console.log( rethobj.heightem + " em " + rethobj.heightpx + " px ; hdiffpx: " + hdiffpx + " ; findwidthpx: " + findwidthpx);
// if we take the width of single line and halve it, we will
// get at least two lines, maybe more - but certainly not less than two lines
// ergo, hdiffpix should always be >= 0
while (hdiffpx > 0) {
// increase slowly findwidthpx; say steps of 10 px
findwidthpx += 10;
rethobj = $("#txtest").getHeightFromWidth( findwidthpx );
hdiffpx = rethobj.heightpx - maxh;
console.log(" in loop: ", rethobj.heightem + " em " + rethobj.heightpx + " px ; hdiffpx: " + hdiffpx + " ; findwidthpx: " + findwidthpx);
}
console.log(" after loop: ", rethobj.heightem + " em " + rethobj.heightpx + " px ; hdiffpx: " + hdiffpx + " ; findwidthpx: " + findwidthpx);
// assign finally
$("#txtest").width(findwidthpx);
}
$(document).ready(ondocready);
</script>
</head>
<body>
<h1>Hello World!</h1>
<div id="txtest" class="a1">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad </div>
</body>
</html>
... and its expected console.log
output is like this:
68.375 em 1094 px ; docw 1386 winw 1386
3.75 em 60 px ; hdiffpx: 20 ; findwidthpx: 547
in loop: 3.75 em 60 px ; hdiffpx: 20 ; findwidthpx: 557
in loop: 3.75 em 60 px ; hdiffpx: 20 ; findwidthpx: 567
in loop: 3.75 em 60 px ; hdiffpx: 20 ; findwidthpx: 577
in loop: 2.5 em 40 px ; hdiffpx: 0 ; findwidthpx: 587
after loop: 2.5 em 40 px ; hdiffpx: 0 ; findwidthpx: 587
If a better answer comes along, I'll re-accept it....