7

So I've got Font Awesome working on my Drupal 7 site. I'm not using the Font Awesome Drupal module. I'm just declaring the style sheet in the template.php.

function genchstyle_preprocess_html(&$variables) {
  drupal_add_css(
    'http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css',
    array('type' => 'external')
  );
}

Now, if I use <i class="icon-search"></i>, I get a nice little magnifying glass icon.

I've recently learned how to replace a form's Submit button with an image like this.

function genchstyle_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['actions']['submit']['#type'] = 'image_button';
    $form['actions']['submit']['#src'] = drupal_get_path('theme', 'genchstyle') . 'images/search.png';
    $form['actions']['submit']['#attributes']['class'][] = 'icon-search';
  }
}

I can't figure out how to replace the submit button with the Font Awesome icon. I tried adapting the above script to use $form['actions']['submit']['#markup'] and I can get it to replace the button with the icon, but then the icon is no longer a functioning submission trigger (or even a link).

I've reviewed all the Font Awesome examples and googled the heck out of this but I can't find a solution.

Any suggestions?

3

7 Answers 7

9

I've been trying to solve the same problem, and I think I've found a solution, but it's a little hacky. I'm hoping that someone else can build on this and make it better.

So, the fundamental problem is that Drupal forms by default use <input type="submit" value="Submit"> and in order to use FontAwesome, you need to apply css which you cannot do to <input>. You can, however, add text and apply css using <button>. So the goal is to replace <input type="submit" value="Submit"> with <button type="submit" value="Submit"><i class="icon-search"></i></button>

In order to add the new form button, I used hook_form_alter in my template.php file in my theme folder (replace MYTHEME with the name of your theme):

function MYTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['actions']['button']['#prefix'] = '<button type="submit" value="Submit">';
    $form['actions']['button']['#suffix'] = '</button>';
    $form['actions']['button']['#markup'] = '<i class="icon-search"></i>';
  }
} 

So this adds the correct markup to the form, but unfortunately, we now have two submit buttons. If you use kpr($form), you can see that there's a default submit button array in $form['actions]['submit']. I tried getting rid of it by using unset($form['actions']['submit]); and also $form['actions']['submit']['#access']=FALSE. Both of these will get rid of the default submit button, but unfortunately, that breaks the search form in Drupal such that upon submission, the user gets sent to the home page with no search results displayed. The form action points to the home page, and then gets redirected to /search/node/[search term], so I'm guessing that Drupal core does some processing that requires the <input> field to redirect to the search results page. I don't know how to make this work with my <button>.

So my hack was to use css to set the default <input> submit button to "display: none", so my form has effectively two submit buttons, but the default one is hidden and only my <button> element with FontAwesome is visible. Now, the search function works, but it seems inelegant to have two submit buttons in the html. If anyone can improve upon this, I'd be very grateful.

3
  • Fyi, it seems there's a slight issue with <button> in ie6 and ie7 (see peterbe.com/plog/button-tag-in-IE). I don't think it applies here since there's only one <button> ... but I have not tested it in ie6/7
    – stevenkkim
    Commented Jun 26, 2013 at 22:20
  • Note that it may still be necessary to include $form['actions']['submit']['#type'] = 'image_button';
    – emc
    Commented Oct 23, 2013 at 22:25
  • unset($form['actions']['submit']['#theme_wrappers']); seems to work.
    – thirdender
    Commented Jun 13, 2014 at 20:18
20

I normal replace search button value into Fontawesome Unicode code.

In your css just define fontawesome font-family.

E.G In your own module call hook_form_alter()

if($form_id = 'search_block_form'){
  $form['actions']['submit']['#value'] = decode_entities('&#xf002;');

}

remeber use decode_entities() to parse the Unicode code.

CSS

.block-search input[type="submit"]{
  border: 0;
  font-size: 1.3em;
  vertical-align: top;
  margin-left: -45px;
  font-family: 'FontAwesome';
}

You should get search icon on button and place inside of your text input field.

ref. Font-Awesome cheatsheet

4
  • 2
    Wow - this is a much more elegant solution - thanks! Commented Aug 5, 2014 at 20:42
  • The 'fa' class doesn't seem to be specific to the <i> tag. I was able to just add the 'fa' class to my input tag and it inherited the necessary font.
    – Dracs
    Commented Mar 10, 2015 at 0:08
  • use of the 'decode_entities' make's error in drupal 8, how can solve that error. Commented Apr 18, 2016 at 8:47
  • In Drupal 8 decode_entities is part of a class api.drupal.org/api/drupal/… Commented Feb 27, 2017 at 19:48
3

I've accomplished this with my own theme function to account for an extra setting in a hook_form_alter. My example is changing the search input from an input to a button. From there I can add classes for pseudo element icons. This would go in the template.php with the proper machine names and form ids swapped out.

/**
 * Implements theme_button().
 */
function THEMENAME_button($variables) {
  $element = $variables['element'];
  $element ['#attributes']['type'] = 'submit';
  element_set_attributes($element, array('id', 'name', 'value'));

  // My custom setting coming from the hook_form_alter below...
  $element_type = isset($element['#element_type']) ? $element['#element_type'] : 'submit';

  $element ['#attributes']['class'][] = 'form-' . $element ['#button_type'];
  if (!empty($element ['#attributes']['disabled'])) {
    $element ['#attributes']['class'][] = 'form-button-disabled';
  }

  // And output a button or input element...
  if ($element_type === 'button') {
    return '<button' . drupal_attributes($element['#attributes']) . '>' . $element['#value'] . '</button>';
  } else {
    return '<input' . drupal_attributes($element['#attributes']) . ' />';
  }
}

/**
 * Implements hook_form_alter().
 */
function THEMENAME_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    // Your FORM ID here...
    case 'search_block_form':
      $form['actions']['submit']['#element_type'] = 'button';
      $form['actions']['submit']['#attributes']['class'][] = 'glyphicon halflings-search';
      break;
    // Add more switch cases to affect other forms...
    case 'FORM_ID':
      break;
  }
}

Of course, you could add another setting in the array to handle markup inside the button. I have not because a button element will allow :after & :before pseudo elements. That was enough for me to get an icon in there and just hiding the default 'Search' text with css.

2

For Drupal 8:

a) If using Bootstrap theme you can use GLYPHICONS setting property #icon in the submit declaration:

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Do something'),
    "#icon" => Bootstrap::glyphicon('chevron-left'),       
);

b) If not using Bootstrap theme or you want icons other than Glyphicons (for example Fontawesome, like in this example), you can customize it a little more, like this:

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Login to Facebook to vote'),
    "#icon" => array(
        '#type' => "html_tag",
        '#tag' => "span",
        '#value' => "",
        '#attributes' =>  array(
            'class' => array("fa","fa-facebook")
        )
    )           
);

I expect this all applies to FORM_ALTER too....

2
  • Hi @ahoms, is #icon perhaps provided by the Bootstrap theme? I can't get it to work, or see any code to support it, in core Drupal 8.
    – mlncn
    Commented Nov 20, 2016 at 16:04
  • #icon is indeed provided by the Bootstrap theme. Commented Nov 20, 2016 at 17:13
2

This is almost the same solution as Steven's, but it replaces the <input> submit with <button> rather than adding such that both exist in the HTML. This comes with the same proviso that IE6/7 doesn't support <button>, and even more so because it removes the possibility that having both as in Steven's solution would at least allow IE6/7 users to press Enter even though the shown button wouldn't work.

This approach below has the benefit that it keeps the HTML markup in template files.

In yourtheme.theme:

/**
 * Implements hook_theme_suggestions_HOOK_alter for form input elements.
 */
function yourtheme_theme_suggestions_input_alter(array &$suggestions, array $variables) {
  $suggestions[] = $variables['theme_hook_original'] . '__' . str_replace('-', '_', $variables['element']['#id']);
}

In the corresponding template suggestion now available, such as templates/input--submit--edit-submit.html, override the core input.html.twig with:

{#
/**
 * @file
 * Overridden theme implementation for an 'input' #type form element.
 *
 * Available variables:
 * - attributes: A list of HTML attributes for the input element.
 * - children: Optional additional rendered elements.
 *
 * @see template_preprocess_input()
 *
 * @ingroup themeable
 */
#}
<button{{ attributes }}>
  <i class="icon-search"></i>
  <span class="visually-hidden">Search</span>
</button>
{{ children }}

A template file like this of course very easy to change or add additional classes or markup.

0

Since the image is added via css class, you shouldn't be using [#type] => 'image_button'. Try this instead:

function genchstyle_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'search_block_form') {
$form['actions']['submit']['#type'] = 'button';
$form['actions']['submit']['#attributes']['class'][] = 'icon-search';
}
3
  • This didn't work. It puts the class in the input tag and it needs to be in its own <i> tag to display the icon. If I could somehow also specify the html tag with something like $form['actions']['submit']['#attributes']['tag'][] = '<i>'; it would work but now I'm just making stuff up! ; ) Commented Jun 21, 2013 at 23:44
  • The fontawesome stylesheet doesn't actually specify an element for the icon-class , i.e .icon-glass:before { content: "\f000"; } .icon-music:before { content: "\f001"; } Try setting width/height/display:block in the CSS
    – adam_bear
    Commented Jun 22, 2013 at 8:10
  • also, font-size ;)
    – adam_bear
    Commented Jun 22, 2013 at 8:18
0

This is how I got this working.

In THEMENAME.theme file I have this, to remove the 'Search' button text:

function THEMENAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-search-content-page-1') {
    $form['actions']['submit']['#value'] = '';    
    }  
  }

The I used CSS Pseudo-elements to add the Search icon on the button like so:

#views-exposed-form-search-content-page-1 button:before {
    font-family: "FontAwesome";
    font-weight: 400;
    content: "\f002";
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.