Quantcast
Channel: Active questions tagged html - Stack Overflow
Viewing all articles
Browse latest Browse all 74020

How can I easily use a 'floating' image to extend a background when a form's content increases?

$
0
0

I have a web-page with a section that contains a form and has a background image, but when the form's contents are validated the form's length grows due to the validation messages displayed beneath the corresponding input fields so that the users can correct their entries. Unfortunately, this causes the form's length to extend beyond the bottom of the form's image, and looks odd.

The background image can't be repeated or stretched to 'fill-in' the larger form varea. Instead, I want initially show the image which has beveled edges and a stippled pattern when the form is first displayed, then when it grows, show the same background, but 'clip' the bottom of the image so that its lower beveled edge doesn't show and then show a second copy of the original un-clipped image positioned behind the clipped image and pushed down from the top of the form so that it second version of the image 'fills-in' the extended area of the longer form.

Because the same background image is used twice then both versions will use the same cached image, reducing storage space and load time.

In the demo, below, there is a grayish colored image used for the form's background and a floating version of the same image that floats just under the form's background. The inputs at the top of the page control the floating image's size and position, but for the most part aren't needed in this version. The (+/-) buttons are used to add and remove lines from the 'form area' so that the background and floating images can be seen to adjust so that the expanding/contracting 'form area' still has a nice looking background behind it.

As I say, below, the demo provided, also below, doesn't quite work when more that 61 lines of text are added to the 'form area'. What needs to happen is that the floating image that shows the bottom bevel needs to also expand so that the combined images can fill-up a 'form-area' of up to about 120 more lines. Of course the larger the background image, the more expansion lines the 'form-area' can accommodate.

Update: I have a mostly working version that is almost right, in that when up to 61 lines of text are added to the 'form area' it looks fine with the background image expanding so it completely fills the form. Beyond 61 lines, the background image splits with the bottom bevel separating from the main background image, leaving a gap. Use either the sliders or the (+/-) buttons to add and remove text from the 'form area'.

Here is the image I'm using as the background:

Background Image.png

And here is the web-page that uses this image:

const TOP = 0, RIGHT = 1, BOTTOM = 2, LEFT = 3, MARGINTOP = 4;

// Top range slider.
const moreText1            = document.querySelector( '#moreText1' );

// Top range slider value.
const moreTextValue1       = document.querySelector( '#moreTextValue1' );

// Bottom range slider.
const moreText2            = document.querySelector( '#moreText2' );

// Bottom range slider value.
const moreTextValue2       = document.querySelector( '#moreTextValue2' );

// Top number inputs.
const inputs               = document.querySelectorAll( 'input' );

const initial_top          = Number( inputs[ TOP ].value );
const initial_clientHeight = document.querySelector( '.bk-img' )
                                     .clientHeight;

const showClip             = document.querySelector( '#showClip' );
const img                  = document.querySelector( 'img' );

var   UNDEFINED;

showClip.innerText         = getImgClip();

function getImgClip() {
  var style     = img.getAttribute( 'style' );

  var styles, il, jl;

  if( style )

    style = style.nodeValue;

  else {

    style  = UNDEFINED;
    styles = document.querySelectorAll( 'style' );
    il     = styles.length;
    for( var i=0; ( ( i < il ) && ( style === UNDEFINED ) ); ++i ) {

      jl   = styles[ i ].sheet.rules.length;
      for( var j=0; j < jl; ++j )
        if( styles[ i ].sheet.rules[ j ].selectorText === 'img' ) {

          style = styles[ i ].sheet.rules[ j ].cssText;
          style = style.substring( style.indexOf( '{' ) + 1,
                                   style.indexOf( '}' ) - 1 ).trim();

          break;

        }

    }

  }

  return style;

}

function change( mode ) {
  var   top            = inputs[ TOP ].value;
  var   right          = inputs[ RIGHT ].value;
  var   bottom         = inputs[ BOTTOM ].value;
  var   left           = inputs[ LEFT ].value;
  var   marginTop      = inputs[ MARGINTOP ].value;
  var   new_top        = document
                        .querySelector( '.bk-img' )
                        .clientHeight +
                          initial_top -
                          initial_clientHeight;
  var   cycle          = ( ( mode !== UNKNOWN ) ? 2 : 1 );

  var   clip;

  do {

    if( mode !== true ) {

      clip             = 'rect( ' + top + 'px, ' +
                                    right  + 'px, ' +
                                    bottom + 'px, ' +
                                    left + 'px )';
      img.style.clip   = clip;

    }
    else {

      clip             = 'rect( ' + new_top + 'px, ' +
                                    right  + 'px, ' +
                                    bottom + 'px, ' +
                                    left + 'px )';
      img.style.clip   = clip;

    }

    if( marginTop !== '0' ) {

      img.style.marginTop = marginTop + 'px';

    }
    else {

      img.style.marginTop = '';

    }

    showClip.innerText = getImgClip();

    mode = UNKNOWN;
    --top;

  } while( cycle-- > 1 );

}
//  change();

function moreText_input( This ) {
  moreText1.value          =
  moreText1.toolTop        =
  moreTextValue1.innerText =
  moreText2.value          =
  moreText2.toolTop        =
  moreTextValue2.innerText = This.value;
}

function moreText_change( This ) {
  //
  // The buttons at the top and bottom of the page incrementally control
  // adding/removing/resetting the content of the text area with each click
  // of these buttons.  Because the action of these buttons is cumulative,
  // the count or amount of lines added/removed in the last call of this
  // function is needed by the current call in order to determine the new
  // number of lines to be put into the text area.  This value is stored in
  // the moreText_change.last_count function attribute.
  //
  // The effect of adding/removing/resetting the content of the text area is
  // to increase/decrease the size of the text area, thus causing more of
  // the background image to be visible, up to the size of the background
  // area.
  //
  // Note, the size of the text area is only determined by the text content
  // and the min_height style, not the background image, thus the bottom or
  // unseen part of the background image is cut-off.  The floating image of
  // the same image is used to 'complete' the background image by showing
  // the bottom bevel using the css clip function.  The only really works
  // when the background image doesn't looks 'odd' because the bevel part
  // doesn't match the background image as it is appended to the truncated
  // background image.
  //

  // The content area from which to add/remove text.
  var text       = document.getElementById( 'text' );

  // The amount of text rows to add/remove.
  var count      = Number( This.value );

  // Indicate add(+)/remove(-) or reset(0).
  var firstChar  = This.value.charAt( 0 );

  // Get the indicated add/remove/reset action.
  var sign       = ( ( firstChar === '-' )
                     ? '-'         // Negatively signed button was used.
                     : ( ( firstChar === '+' )
                         ? '+'     // Positively signed button was used.
                         : ( ( firstChar === '0' )
                             ? '0' // Reset button or range slider at 0 was used.
                             : '?' ) ) );  // The range slider was used.

  // Get the last_count value, if it exists.
  var last_count = ( ( moreText_change.last_count === undefined )
                     ? 1
                     : moreText_change.last_count );

  text.innerHTML = 'Hello World!'; // Reset the text area's content to one line.

  //
  // When sign is '?', then the range slider was used and its value was
  // greater than zero, set the text area to the number of lines specified
  // by count.
  //

  //
  // If the sign of the button control's value is plus(+), minus(-), or
  // reset(0), then change the text area's content by the amount of lines in
  // count.
  //
  // If the sign of the button control's value is a question mark(?), then
  // the range slider was used.
  //
  // Assign the updated number of text lines to count and the function
  // attribute, last_count, then add the lines to the text area.
  //

  if( sign !== '?' ) {

    if( ( count >= 0 ) && ( sign !== '-' ) ) {

      // This branch handles the plus(+) and reset(0) cases.

      // Count is 0 or a positive value.

      count = ( ( sign === '+' ) ? last_count + count : count );          

      // Keep count equal to or under the max range.

      count = Math.min( count, Number( moreText1.max ) );

    }
    else {

      //
      // This branch is similar to the above case, except that only the
      // minus(-) case is handled here.
      //

      // Count is a negative number.

      count = last_count + count;

      // If the new total is less than 0, set count to 0.

      count = Math.max( 0, count );

    }

  }

  for( var i=1; i < count; ++i )
    text.innerHTML += '<br />' + 'Hello World!';

  moreText_change.last_count   = ( count ? count : 1 );
  moreText1.value              =
  moreText2.value              = Math.max( 0, moreText_change.last_count );

//    change( true );

  showClip.innerText           = getImgClip();

}
body { width: 893px; }
.vac { padding: 33px 0; }
.bk-img  {
  position: relative;
  background-repeat: no-repeat;
  background-image: url("https://i.stack.imgur.com/fBj4I.jpg");
  background-color: lightgray;
  color: white;
  min-height: 68px;
}
.area { background-color: lightgray; }
img {
  position: absolute;
  bottom: 0;
  left: 0;
  clip: rect( 1080px, 893px, 1148px, 0px );
  margin-top: -1149px;
}
<p><div style="display: none;">
    top:&nbsp;<input type="number" id="top"
                     onchange="change();" value=1080 />&nbsp;&nbsp;
    right:&nbsp;<input type="number" id="right"
                       onchange="change();" value=893 />&nbsp;&nbsp;
    bottom:&nbsp;<input type="number" id="bottom"
                        onchange="change();" value=1148 />&nbsp;&nbsp;
    left:&nbsp;<input type="number" id="top"
                      onchange="change();" value=0 /><br /><br />
    marginTop:&nbsp;<input type="number" id="margintop"
                           onchange="change();" value=-1149 /></div>
  More&nbsp;Text:&nbsp;&nbsp;<div style="display: inline-block; position: relative;  width: 134px;"><input type="range" id="moreText1"
           style="position: absolute; margin-top: -1px;"
           min="0" max="99" value="0"
           tooltip="0"
           oninput="moreText_input( this );"
           onchange="moreText_change( this );" />&nbsp;&nbsp;</div><div id="moreTextValue1"
       style="display: inline-block; width: 19px;">0</div>&nbsp;&nbsp;<div style="display: inline-block; margin-top: 10px;"><button value=-50
            onclick="moreText_change( this );">-50</button>&nbsp;<button value=-25
            onclick="moreText_change( this );">-25</button>&nbsp;<button value=-10
            onclick="moreText_change( this );">-10</button>&nbsp;<button value=-5
            onclick="moreText_change( this );">-5</button>&nbsp;<button value=-1
            onclick="moreText_change( this );">-1</button>&nbsp;&nbsp;<button value=0
            onclick="moreText_change( this );">0</button>&nbsp;<button value=+1
            onclick="moreText_change( this );">+1</button>&nbsp;<button value=+5
            onclick="moreText_change( this );">+5</button>&nbsp;<button value=+10
            onclick="moreText_change( this );">+10</button>&nbsp;<button value=+25
            onclick="moreText_change( this );">+25</button>&nbsp;<button value=+50
            onclick="moreText_change( this );">+50</button>&nbsp;</div><p id="showClip"></p></p><div class="area"><div class="vac"><h1>The background-image Property</h1></div></div><div class="bk-img"><div id="text"
       class="vac"
       style="position: relative; z-index: 100; text-align: center;">
    Hello World!</div><img src="https://i.stack.imgur.com/fBj4I.jpg" /></div><div class="area"><div class="vac">footer area</div></div><div>&nbsp;</div>
More&nbsp;Text:&nbsp;&nbsp;<div style="display: inline-block; position: relative; width: 134px;"><input type="range" id="moreText2"
         style="position: absolute; margin-top: -1px;"
         min="0" max="99" value="0"
         tooltip="0"
         oninput="moreText_input( this );"
         onchange="moreText_change( this );" />&nbsp;&nbsp;</div><div id="moreTextValue2"
     style="display: inline-block; width: 19px;">0</div>&nbsp;&nbsp;<button value=-50
        onclick="moreText_change( this );">-50</button>&nbsp;<button value=-25
        onclick="moreText_change( this );">-25</button>&nbsp;<button value=-10
        onclick="moreText_change( this );">-10</button>&nbsp;<button value=-5
        onclick="moreText_change( this );">-5</button>&nbsp;<button value=-1
        onclick="moreText_change( this );">-1</button>&nbsp;&nbsp;<button value=0
        onclick="moreText_change( this );">0</button>&nbsp;<button value=+1
        onclick="moreText_change( this );">+1</button>&nbsp;<button value=+5
        onclick="moreText_change( this );">+5</button>&nbsp;<button value=+10
        onclick="moreText_change( this );">+10</button>&nbsp;<button value=+25
        onclick="moreText_change( this );">+25</button>&nbsp;<button value=+50
        onclick="moreText_change( this );">+50</button>&nbsp;

Thanks.


Viewing all articles
Browse latest Browse all 74020

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>